Thread Tools Display Modes
09-18-20, 08:03 PM   #1
siweia
A Flamescale Wyrmkin
 
siweia's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2011
Posts: 126
ScrollFrame seems to have a limit height in the patch 9.0.2.35938

Lua Code:
  1. local _, ns = ...
  2. local B, C, L, DB = unpack(ns)
  3. if not C.Infobar.Guild then return end
  4.  
  5. local module = B:GetModule("Infobar")
  6. local info = module:RegisterInfobar("Guild", C.Infobar.GuildPos)
  7.  
  8. local wipe, sort, format, select = table.wipe, table.sort, format, select
  9. local CLASS_ICON_TCOORDS, SELECTED_DOCK_FRAME = CLASS_ICON_TCOORDS, SELECTED_DOCK_FRAME
  10. local LEVEL_ABBR, CLASS_ABBR, NAME, ZONE, RANK, GUILDINFOTAB_APPLICANTS, REMOTE_CHAT = LEVEL_ABBR, CLASS_ABBR, NAME, ZONE, RANK, GUILDINFOTAB_APPLICANTS, REMOTE_CHAT
  11. local IsAltKeyDown, IsShiftKeyDown, C_Timer_After, GetTime, Ambiguate, MouseIsOver = IsAltKeyDown, IsShiftKeyDown, C_Timer.After, GetTime, Ambiguate, MouseIsOver
  12. local MailFrameTab_OnClick, MailFrame, SendMailNameEditBox = MailFrameTab_OnClick, MailFrame, SendMailNameEditBox
  13. local ChatEdit_ChooseBoxForSend, ChatEdit_ActivateChat, ChatFrame_OpenChat, ChatFrame_GetMobileEmbeddedTexture = ChatEdit_ChooseBoxForSend, ChatEdit_ActivateChat, ChatFrame_OpenChat, ChatFrame_GetMobileEmbeddedTexture
  14. local GetNumGuildMembers, GetGuildInfo, GetNumGuildApplicants, GetGuildRosterInfo, IsInGuild = GetNumGuildMembers, GetGuildInfo, GetNumGuildApplicants, GetGuildRosterInfo, IsInGuild
  15. local GetQuestDifficultyColor, GetRealZoneText, UnitInRaid, UnitInParty = GetQuestDifficultyColor, GetRealZoneText, UnitInRaid, UnitInParty
  16. local C_GuildInfo_GuildRoster = C_GuildInfo.GuildRoster
  17. local InviteToGroup = C_PartyInfo.InviteUnit
  18.  
  19. local r, g, b = DB.r, DB.g, DB.b
  20. local infoFrame, gName, gOnline, gApps, gRank, applyData, prevTime
  21.  
  22. local function scrollBarHook(self, delta)
  23.     local scrollBar = self.ScrollBar
  24.     scrollBar:SetValue(scrollBar:GetValue() - delta*50)
  25. end
  26.  
  27. function module:ReskinScrollBar()
  28.     local scrollBar = self.ScrollBar
  29.     B.HideObject(scrollBar.ScrollUpButton)
  30.     B.HideObject(scrollBar.ScrollDownButton)
  31.     scrollBar.ThumbTexture:SetColorTexture(.3, .3, .3)
  32.     scrollBar.ThumbTexture:SetSize(3, 10)
  33.     scrollBar.ThumbTexture:SetPoint("LEFT", -5, 0)
  34.     self:SetScript("OnMouseWheel", scrollBarHook)
  35. end
  36.  
  37. local function setupInfoFrame()
  38.     if infoFrame then infoFrame:Show() return end
  39.  
  40.     infoFrame = CreateFrame("Frame", "NDuiGuildInfobar", info)
  41.     infoFrame:SetSize(335, 495)
  42.     infoFrame:SetPoint("TOPLEFT", UIParent, 15, -30)
  43.     infoFrame:SetClampedToScreen(true)
  44.     infoFrame:SetFrameStrata("TOOLTIP")
  45.     local bg = B.SetBD(infoFrame)
  46.     bg:SetBackdropColor(0, 0, 0, .7)
  47.  
  48.     local function onUpdate(self, elapsed)
  49.         self.timer = (self.timer or 0) + elapsed
  50.         if self.timer > .1 then
  51.             if not infoFrame:IsMouseOver() then
  52.                 self:Hide()
  53.                 self:SetScript("OnUpdate", nil)
  54.             end
  55.  
  56.             self.timer = 0
  57.         end
  58.     end
  59.     infoFrame:SetScript("OnLeave", function(self)
  60.         self:SetScript("OnUpdate", onUpdate)
  61.     end)
  62.  
  63.     gName = B.CreateFS(infoFrame, 16, "Guild", true, "TOPLEFT", 15, -10)
  64.     gOnline = B.CreateFS(infoFrame, 13, "Online", false, "TOPLEFT", 15, -35)
  65.     gApps = B.CreateFS(infoFrame, 13, "Applications", false, "TOPRIGHT", -15, -35)
  66.     gRank = B.CreateFS(infoFrame, 13, "Rank", false, "TOPLEFT", 15, -51)
  67.  
  68.     local bu = {}
  69.     local width = {30, 35, 126, 126}
  70.     for i = 1, 4 do
  71.         bu[i] = CreateFrame("Button", nil, infoFrame)
  72.         bu[i]:SetSize(width[i], 22)
  73.         bu[i]:SetFrameLevel(infoFrame:GetFrameLevel() + 3)
  74.         if i == 1 then
  75.             bu[i]:SetPoint("TOPLEFT", 12, -75)
  76.         else
  77.             bu[i]:SetPoint("LEFT", bu[i-1], "RIGHT", -2, 0)
  78.         end
  79.         bu[i].HL = bu[i]:CreateTexture(nil, "HIGHLIGHT")
  80.         bu[i].HL:SetAllPoints(bu[i])
  81.         bu[i].HL:SetColorTexture(r, g, b, .2)
  82.     end
  83.     B.CreateFS(bu[1], 13, LEVEL_ABBR)
  84.     B.CreateFS(bu[2], 13, CLASS_ABBR)
  85.     B.CreateFS(bu[3], 13, NAME, false, "LEFT", 5, 0)
  86.     B.CreateFS(bu[4], 13, ZONE, false, "RIGHT", -5, 0)
  87.  
  88.     for i = 1, 4 do
  89.         bu[i]:SetScript("OnClick", function()
  90.             NDuiADB["GuildSortBy"] = i
  91.             NDuiADB["GuildSortOrder"] = not NDuiADB["GuildSortOrder"]
  92.             applyData()
  93.         end)
  94.     end
  95.  
  96.     B.CreateFS(infoFrame, 13, DB.LineString, false, "BOTTOMRIGHT", -12, 58)
  97.     local whspInfo = DB.InfoColor..DB.RightButton..L["Whisper"]
  98.     B.CreateFS(infoFrame, 13, whspInfo, false, "BOTTOMRIGHT", -15, 42)
  99.     local invtInfo = DB.InfoColor.."ALT +"..DB.LeftButton..L["Invite"]
  100.     B.CreateFS(infoFrame, 13, invtInfo, false, "BOTTOMRIGHT", -15, 26)
  101.     local copyInfo = DB.InfoColor.."SHIFT +"..DB.LeftButton..L["Copy Name"]
  102.     B.CreateFS(infoFrame, 13, copyInfo, false, "BOTTOMRIGHT", -15, 10)
  103.  
  104.     local scrollFrame = CreateFrame("ScrollFrame", nil, infoFrame, "UIPanelScrollFrameTemplate")
  105.     scrollFrame:SetSize(315, 320)
  106.     scrollFrame:SetPoint("TOPLEFT", 10, -100)
  107.     module.ReskinScrollBar(scrollFrame)
  108.  
  109.     local roster = CreateFrame("Frame", nil, scrollFrame)
  110.     roster:SetSize(315, 1)
  111.     scrollFrame:SetScrollChild(roster)
  112.     infoFrame.roster = roster
  113. end
  114.  
  115. local guildTable, frames, previous = {}, {}, 0
  116.  
  117. local function buttonOnClick(self, btn)
  118.     local name = guildTable[self.index][3]
  119.     if btn == "LeftButton" then
  120.         if IsAltKeyDown() then
  121.             InviteToGroup(name)
  122.         elseif IsShiftKeyDown() then
  123.             if MailFrame:IsShown() then
  124.                 MailFrameTab_OnClick(nil, 2)
  125.                 SendMailNameEditBox:SetText(name)
  126.                 SendMailNameEditBox:HighlightText()
  127.             else
  128.                 local editBox = ChatEdit_ChooseBoxForSend()
  129.                 local hasText = (editBox:GetText() ~= "")
  130.                 ChatEdit_ActivateChat(editBox)
  131.                 editBox:Insert(name)
  132.                 if not hasText then editBox:HighlightText() end
  133.             end
  134.         end
  135.     else
  136.         ChatFrame_OpenChat("/w "..name.." ", SELECTED_DOCK_FRAME)
  137.     end
  138. end
  139.  
  140. local function createRoster(parent, i)
  141.     local button = CreateFrame("Button", nil, parent)
  142.     button:SetSize(312, 20)
  143.     button.HL = button:CreateTexture(nil, "HIGHLIGHT")
  144.     button.HL:SetAllPoints()
  145.     button.HL:SetColorTexture(r, g, b, .2)
  146.     button.index = i
  147.  
  148.     button.level = B.CreateFS(button, 13, "Level", false)
  149.     button.level:SetPoint("TOP", button, "TOPLEFT", 16, -4)
  150.     button.class = button:CreateTexture(nil, "ARTWORK")
  151.     button.class:SetPoint("LEFT", 35, 0)
  152.     button.class:SetSize(16, 16)
  153.     button.class:SetTexture("Interface\\GLUES\\CHARACTERCREATE\\UI-CHARACTERCREATE-CLASSES")
  154.     button.name = B.CreateFS(button, 13, "Name", false, "LEFT", 65, 0)
  155.     button.name:SetPoint("RIGHT", button, "LEFT", 185, 0)
  156.     button.name:SetJustifyH("LEFT")
  157.     button.zone = B.CreateFS(button, 13, "Zone", false, "RIGHT", -2, 0)
  158.     button.zone:SetPoint("LEFT", button, "RIGHT", -120, 0)
  159.     button.zone:SetJustifyH("RIGHT")
  160.  
  161.     button:RegisterForClicks("AnyUp")
  162.     button:SetScript("OnClick", buttonOnClick)
  163.  
  164.     return button
  165. end
  166.  
  167. C_Timer_After(5, function()
  168.     if IsInGuild() then C_GuildInfo_GuildRoster() end
  169. end)
  170.  
  171. local function setPosition()
  172.     for i = 1, previous do
  173.         if i == 1 then
  174.             frames[i]:SetPoint("TOPLEFT")
  175.         else
  176.             frames[i]:SetPoint("TOP", frames[i-1], "BOTTOM")
  177.         end
  178.         frames[i]:Show()
  179.     end
  180. end
  181.  
  182. local function refreshData()
  183.     if not prevTime or (GetTime()-prevTime > 5) then
  184.         C_GuildInfo_GuildRoster()
  185.         prevTime = GetTime()
  186.     end
  187.  
  188.     wipe(guildTable)
  189.     local count = 0
  190.     local total, _, online = GetNumGuildMembers()
  191.     local guildName, guildRank = GetGuildInfo("player")
  192.  
  193.     gName:SetText("|cff0099ff<"..(guildName or "")..">")
  194.     gOnline:SetText(format(DB.InfoColor.."%s:".." %d/%d", GUILD_ONLINE_LABEL, online, total))
  195.     gApps:SetText(format(DB.InfoColor..GUILDINFOTAB_APPLICANTS, GetNumGuildApplicants()))
  196.     gRank:SetText(DB.InfoColor..RANK..": "..(guildRank or ""))
  197.  
  198.     for i = 1, total do
  199.         local name, _, _, level, _, zone, _, _, connected, status, class, _, _, mobile = GetGuildRosterInfo(i)
  200.         if connected or mobile then
  201.             if mobile and not connected then
  202.                 zone = REMOTE_CHAT
  203.                 if status == 1 then
  204.                     status = "|TInterface\\ChatFrame\\UI-ChatIcon-ArmoryChat-AwayMobile:14:14:0:0:16:16:0:16:0:16|t"
  205.                 elseif status == 2 then
  206.                     status = "|TInterface\\ChatFrame\\UI-ChatIcon-ArmoryChat-BusyMobile:14:14:0:0:16:16:0:16:0:16|t"
  207.                 else
  208.                     status = ChatFrame_GetMobileEmbeddedTexture(73/255, 177/255, 73/255)
  209.                 end
  210.             else
  211.                 if status == 1 then
  212.                     status = DB.AFKTex
  213.                 elseif status == 2 then
  214.                     status = DB.DNDTex
  215.                 else
  216.                     status = " "
  217.                 end
  218.             end
  219.             if not zone then zone = UNKNOWN end
  220.  
  221.             count = count + 1
  222.             guildTable[count] = {level, class, Ambiguate(name, "none"), zone, status}
  223.         end
  224.     end
  225.  
  226.     if count ~= previous then
  227.         if count > previous then
  228.             for i = previous+1, count do
  229.                 if not frames[i] then
  230.                     frames[i] = createRoster(infoFrame.roster, i)
  231.                 end
  232.             end
  233.         elseif count < previous then
  234.             for i = count+1, previous do
  235.                 frames[i]:Hide()
  236.             end
  237.         end
  238.         previous = count
  239.  
  240.         setPosition()
  241.     end
  242. end
  243.  
  244. local function sortGuild(a, b)
  245.     if a and b then
  246.         if NDuiADB["GuildSortOrder"] then
  247.             return a[NDuiADB["GuildSortBy"]] < b[NDuiADB["GuildSortBy"]]
  248.         else
  249.             return a[NDuiADB["GuildSortBy"]] > b[NDuiADB["GuildSortBy"]]
  250.         end
  251.     end
  252. end
  253.  
  254. function applyData()
  255.     sort(guildTable, sortGuild)
  256.  
  257.     for i = 1, previous do
  258.         local level, class, name, zone, status = unpack(guildTable[i])
  259.  
  260.         local levelcolor = B.HexRGB(GetQuestDifficultyColor(level))
  261.         frames[i].level:SetText(levelcolor..level)
  262.  
  263.         local tcoords = CLASS_ICON_TCOORDS[class]
  264.         frames[i].class:SetTexCoord(tcoords[1] + .022, tcoords[2] - .025, tcoords[3] + .022, tcoords[4] - .025)
  265.  
  266.         local namecolor = B.HexRGB(B.ClassColor(class))
  267.         frames[i].name:SetText(namecolor..name..status)
  268.  
  269.         local zonecolor = DB.GreyColor
  270.         if UnitInRaid(name) or UnitInParty(name) then
  271.             zonecolor = "|cff4c4cff"
  272.         elseif GetRealZoneText() == zone then
  273.             zonecolor = "|cff4cff4c"
  274.         end
  275.         frames[i].zone:SetText(zonecolor..zone)
  276.     end
  277. end
  278.  
  279. info.eventList = {
  280.     "PLAYER_ENTERING_WORLD",
  281.     "GUILD_ROSTER_UPDATE",
  282.     "PLAYER_GUILD_UPDATE",
  283. }
  284.  
  285. info.onEvent = function(self, event, ...)
  286.     if not IsInGuild() then
  287.         self.text:SetText(GUILD..": "..DB.MyColor..NONE)
  288.         return
  289.     end
  290.  
  291.     if event == "GUILD_ROSTER_UPDATE" then
  292.         local canRequestRosterUpdate = ...
  293.         if canRequestRosterUpdate then
  294.             C_GuildInfo_GuildRoster()
  295.         end
  296.     end
  297.  
  298.     local online = select(3, GetNumGuildMembers())
  299.     self.text:SetText(GUILD..": "..DB.MyColor..online)
  300.  
  301.     if infoFrame and infoFrame:IsShown() then
  302.         refreshData()
  303.         applyData()
  304.     end
  305. end
  306.  
  307. info.onEnter = function()
  308.     if not IsInGuild() then return end
  309.     if NDuiFriendsFrame and NDuiFriendsFrame:IsShown() then NDuiFriendsFrame:Hide() end
  310.     setupInfoFrame()
  311.     refreshData()
  312.     applyData()
  313. end
  314.  
  315. local function delayLeave()
  316.     if MouseIsOver(infoFrame) then return end
  317.     infoFrame:Hide()
  318. end
  319.  
  320. info.onLeave = function()
  321.     if not infoFrame then return end
  322.     C_Timer_After(.1, delayLeave)
  323. end
  324.  
  325. info.onMouseUp = function()
  326.     if InCombatLockdown() then UIErrorsFrame:AddMessage(DB.InfoColor..ERR_NOT_IN_COMBAT) return end
  327.  
  328.     if not IsInGuild() then return end
  329.     infoFrame:Hide()
  330.     if not GuildFrame then LoadAddOn("Blizzard_GuildUI") end
  331.     ToggleFrame(GuildFrame)
  332. end

You can also read from my Github.

Because blizzard prevent player from opening GuildFrame in combat, I use the code above to create a frame that display guild members with copy name and invite unit function, as a replacement of GameTooltip.

In the newest beta patch, once the online members go more than 97, the scrollframe becomes none scroll-able, no idea how to get a fix.

Last edited by siweia : 09-18-20 at 08:06 PM.
  Reply With Quote
09-18-20, 08:32 PM   #2
kurapica.igas
A Chromatic Dragonspawn
Join Date: Aug 2011
Posts: 152
When you done with refreshData, you need use scrollFrame:UpdateScrollChildRect() to update the scrollchild's height based on those roster buttons, or you could adjust the scroll child's height based on the visible buttons's count.

Edit. Seems there is no need to call the UpdateScrollChildRect manually, the OnScrollRangeChanged works for it.

Also for your code, you can set those buttons's location when you create them, no need to repeat setPosition for each time.

Seems there is no error in those code, could be a bug to be checked again when 9.0 started.

Last edited by kurapica.igas : 09-19-20 at 07:01 AM.
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » ScrollFrame seems to have a limit height in the patch 9.0.2.35938

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off