Advertisement
Guest User

CalendarExtras sorting hack

a guest
Jun 19th, 2012
28
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 12.96 KB | None | 0 0
  1. -- New sorting buttons for the invite lists
  2. -- @file-revision@
  3.  
  4. local core = CalendarExtras
  5.  
  6. local module = core:NewModule("Sorters")
  7.  
  8.  --[[ -------- Locals ------- ]]--
  9.  
  10. local overrideSort, sortReverse
  11. local listIsDirty
  12.  
  13. local roles -- This will point to the roles-table in the savedvars file after OnInit
  14.  
  15. -- Todo: Maybe add hybrid to the list... should've made these into icons in the first place
  16. local roleIndexToName = {
  17.     "Tank", -- [1]
  18.     "Heal", -- [2]
  19.     "DPS",  -- [3]
  20.     "?"     -- [4]
  21. }
  22. local roleColors = {
  23.     { r = 0.78, g = 0.61, b = 0.43 }, -- Tank
  24.     { r = 0.1,  g = 1,    b = 0.1 },  -- Healer
  25.     { r = 1,    g = 0.1,  b = 0.1 },  -- DPS
  26.     NORMAL_FONT_COLOR                 -- No role
  27. }
  28. local knownRolesPerClass = {
  29.     MAGE    = 3,
  30.     HUNTER  = 3,
  31.     ROGUE   = 3,
  32.     WARLOCK = 3
  33. }
  34.  
  35. local massSelectModule
  36.  
  37.  --[[ ----------------------- ]]--
  38.  
  39. local SortList
  40.  
  41. do
  42.     local statusTable, roleTable, classTable, inviteIndexTable = {}, {}, {}, {}
  43.  
  44.     -- Need to move the status codes around so they sort in more sensible way
  45.     --  1.Invited, 5.Out, 3.Declined, 8.Notsignedup, 9.Tentative, 6.Standby, 7.Signedup  2.Accepted, 4.Confirmed
  46.     --  1          2      3           4              5            6          7           8           9        
  47.     local statusSwap = {
  48. --      1, 2, 3, 4, 5, 6, 7, 8, 9 =>
  49.         1, 8, 3, 9, 2, 6, 7, 4, 5
  50.     }
  51.     local function Sorter(name1, name2)
  52.         if overrideSort == "role" then
  53.             if roleTable[name1] == roleTable[name2] then
  54.                 if statusTable[name1] == statusTable[name2] then
  55.                     return name1 < name2
  56.                 else
  57.                     return statusTable[name1] > statusTable[name2]
  58.                 end
  59.             else
  60.                 return roleTable[name1] < roleTable[name2]
  61.             end
  62.         elseif overrideSort == "mystatus" then -- Hax to sort status by status -> role -> class -> name, rather than status -> name
  63.             if statusTable[name1] == statusTable[name2] then
  64.                 if roleTable[name1] == roleTable[name2] then
  65.                     if classTable[name1] == classTable[name2] then
  66.                         return name1 < name2
  67.                     else
  68.                         return classTable[name1] < classTable[name2]
  69.                     end
  70.                 else
  71.                     return roleTable[name1] < roleTable[name2]
  72.                 end
  73.             else
  74.                 return statusTable[name1] > statusTable[name2]
  75.             end
  76.         end
  77.     end
  78.  
  79.     function SortList()
  80.         local t, i = {}, 1
  81.         while true do
  82.             local name, level, _, class, inviteStatus = CalendarEventGetInvite(i)
  83.             if not name then break end
  84.             t[i] = name
  85.             statusTable[name] = statusSwap[inviteStatus] or inviteStatus
  86.             roleTable[name] = module:GetRole(name, class)
  87.             classTable[name] = class
  88.             inviteIndexTable[name] = i
  89.             i = i + 1
  90.         end
  91.         table.sort(t, Sorter)
  92.         for k, v in ipairs(t) do
  93.             module.reSortedList[k] = inviteIndexTable[v]
  94.         end
  95.         wipe(statusTable)
  96.         wipe(roleTable)
  97.         wipe(classTable)
  98.         wipe(inviteIndexTable)
  99.     end
  100. end
  101.  
  102. local function NewSorterOnClick(updateFunc, self, button, down)
  103.     core.callbacks:Fire("Pre_Sort", true)
  104.     overrideSort = "role"
  105.     if #module.reSortedList == 0 then
  106.         SortList()
  107.     end
  108.     if sortReverse == nil then -- Default to forward sort
  109.         sortReverse = false
  110.     else
  111.         sortReverse = not sortReverse
  112.     end
  113.     PlaySound("igMainMenuOptionCheckBoxOn");
  114.     CalendarContextMenu_Hide(CalendarViewEventInviteContextMenu_Initialize)
  115.     CalendarContextMenu_Hide(CalendarCreateEventInviteContextMenu_Initialize)
  116.     local _,  _,  _,  _,  _,  _,  _, _,  _,  _,  _,  _,  _,  _,  _,  _,  _,  _,  _,  _,  _,  _,  _, inviteType, calendarType = CalendarGetEventInfo()
  117.     updateFunc(inviteType, calendarType)
  118.     core.callbacks:Fire("Post_Sort", true)
  119. end
  120.  
  121. local function UpdateInviteListButtons(_, frame)
  122.     local name, class, role, roleButton, c, _
  123.     for _, button in ipairs(frame.buttons) do
  124.         if not button.inviteIndex then break end
  125.         name, _, _, class = CalendarEventGetInvite(button.inviteIndex)
  126.         roleButton = _G[button:GetName().."Role"]
  127.         role = module:GetRole(name, class)
  128.         c = roleColors[role]
  129.         roleButton:SetText(roleIndexToName[role])
  130.         roleButton:SetTextColor(c.r, c.g, c.b)
  131.     end
  132. end
  133.  
  134. local function ClearCustomSort(_, custom)
  135.     if custom then return end
  136.     wipe(module.reSortedList)
  137.     overrideSort = nil
  138.     sortReverse = nil
  139.     listIsDirty = nil
  140. end
  141.  
  142. function module:SetRole(name, role)
  143.     if not name or not role then return end
  144.     roles[name] = role ~= 4 and role or nil
  145.     if overrideSort then
  146.         wipe(module.reSortedList)
  147.         SortList()
  148.     end
  149. end
  150.  
  151. function module:GetRole(name, class)
  152.     if name then
  153.         if roles[name] then
  154.             return roles[name]
  155.         end
  156.     end
  157.     if class and knownRolesPerClass[class] then
  158.         return knownRolesPerClass[class]
  159.     end
  160.     return 4
  161. end
  162.  
  163. function module:OnInitialize()
  164.     -- Set up our roles database
  165.     if not core.db.roles then
  166.         core.db.rolesDBver = 1 -- Think I screwed up when I didn't add hybirds, might have to update the tables at some point, so lets assign a version to it
  167.         core.db.roles = {}
  168.     end
  169.     roles = core.db.roles
  170.  
  171.     module.reSortedList = {}
  172.  
  173.     if core.modules["Mass Select"] then
  174.         massSelectModule = core.modules["Mass Select"]
  175.     end
  176.  
  177.     if core.modules.Export then
  178.         core.modules.Export:AddFormatToken("ROLE", "Role", function(name, class) return roleIndexToName[self:GetRole(name, class)] end)
  179.     end
  180.  
  181.     -- Create the new sorting buttons
  182.     -- TODO: The direction arrow is overlapped by the Role text for some reason
  183.     local viewBtn = CreateFrame("Button", "CalendarViewEventInviteListRoleSortButton", CalendarViewEventInviteList, "CalendarEventInviteSortButtonTemplate")
  184.     local createBtn = CreateFrame("Button", "CalendarCreateEventInviteListRoleSortButton", CalendarCreateEventInviteList, "CalendarEventInviteSortButtonTemplate")
  185.  
  186.     viewBtn:SetText("Role")
  187.     viewBtn:SetPoint("BOTTOM", CalendarViewEventInviteList, "TOP", 3, 0)
  188.     viewBtn.criterion = "role"
  189.  
  190.     createBtn:SetText("Role")
  191.     createBtn:SetPoint("BOTTOM", CalendarCreateEventInviteList, "TOP", 3, 0)
  192.     createBtn.criterion = "role"
  193.  
  194.     local width = viewBtn:GetTextWidth() + _G["CalendarViewEventInviteListRoleSortButtonDirection"]:GetWidth()
  195.     viewBtn:SetWidth(width)
  196.     createBtn:SetWidth(width)
  197.  
  198.     viewBtn:SetScript("OnClick", function(...) NewSorterOnClick(CalendarViewEventInviteList_Update, ...) end)
  199.     createBtn:SetScript("OnClick", function(...) NewSorterOnClick(CalendarCreateEventInviteList_Update, ...) end)
  200.  
  201.     CalendarViewEventInviteList.sortButtons["role"] = viewBtn
  202.     CalendarCreateEventInviteList.sortButtons["role"] = createBtn
  203.  
  204.     -- This is kinda stupid, would be better to modify the templates, but I'm not sure how to do that before the frames get created, if that's even possible
  205.     local function Modify(button)
  206.         local buttonName = button:GetName()
  207.         local --[[name,]] class, status, role = --[[_G[buttonName.."Name"],]] _G[buttonName.."Class"], _G[buttonName.."Status"], button:CreateFontString(buttonName.."Role", "BORDER", "GameFontNormalSmall")
  208.  
  209.         class:SetWidth(70)
  210.         class:ClearAllPoints()
  211.         class:SetPoint("RIGHT", -110, 0)
  212.         class:SetJustifyH("RIGHT")
  213.  
  214.         status:ClearAllPoints()
  215.         status:SetPoint("RIGHT", -35, 0)
  216.         status:SetJustifyH("RIGHT")
  217.  
  218.         role:SetWidth(30)
  219.         role:SetJustifyH("RIGHT")
  220.         role:SetPoint("RIGHT")
  221.     end
  222.     for _, button in ipairs(CalendarViewEventInviteList.scrollFrame.buttons) do
  223.         Modify(button)
  224.     end
  225.     for _, button in ipairs(CalendarCreateEventInviteList.scrollFrame.buttons) do
  226.         Modify(button)
  227.     end
  228.  
  229.     self:RegisterEvent("CALENDAR_UPDATE_INVITE_LIST", function()
  230.         if overrideSort then
  231.             listIsDirty = true
  232.         end
  233.     end)
  234.  
  235.     -- The main hook to swap player indices around
  236.     core.CalendarEventGetInviteHandler = self.CalendarEventGetInvite
  237.  
  238.     -- Clear everything before lists update after event is opened
  239.     core.RegisterCallback(self, "OpenEvent", ClearCustomSort)
  240.     -- Clear everything when list is resorted
  241.     core.RegisterCallback(self, "Pre_Sort", ClearCustomSort)
  242.  
  243.     -- Resort before list is updated if needed
  244.     core.RegisterCallback(self, "Pre_Update", function()
  245.         if listIsDirty then
  246.             listIsDirty = nil
  247.             wipe(module.reSortedList)
  248.             SortList()
  249.         end
  250.     end)
  251.  
  252.     -- Go through the buttons after list is updated by the game
  253.     --core.RegisterCallback(module, "Pre_Post_Update", UpdateInviteListButtons)
  254.     core.RegisterCallback(self, "Post_Update", UpdateInviteListButtons)
  255.  
  256.     -- Hook the sort button functions
  257.     self:RawHook("CalendarEventInviteList_AnchorSortButtons", true)
  258.  
  259.     -- Env proxy for the CalendarEventInviteList_UpdateSortButtons
  260.     self:RawHook("CalendarEventGetInviteSortCriterion", true)
  261.  
  262.     local function StatusSortButtonOverride(frame, ...)
  263.         core.callbacks:Fire("Pre_Sort", true)
  264.         overrideSort = "mystatus"
  265.         if #module.reSortedList == 0 then
  266.             SortList()
  267.         end
  268.         if sortReverse == nil then -- Default to forward sort
  269.             sortReverse = false
  270.         else
  271.             sortReverse = not sortReverse
  272.         end
  273.         PlaySound("igMainMenuOptionCheckBoxOn");
  274.         CalendarContextMenu_Hide(CalendarViewEventInviteContextMenu_Initialize)
  275.         CalendarContextMenu_Hide(CalendarCreateEventInviteContextMenu_Initialize)
  276.         local _,  _,  _,  _,  _,  _,  _, _,  _,  _,  _,  _,  _,  _,  _,  _,  _,  _,  _,  _,  _,  _,  _, inviteType, calendarType = CalendarGetEventInfo()
  277.         if frame == CalendarViewEventInviteListStatusSortButton then
  278.             CalendarViewEventInviteList_Update(inviteType, calendarType)
  279.         elseif frame == CalendarCreateEventInviteListStatusSortButton then
  280.             CalendarCreateEventInviteList_Update(inviteType, calendarType)
  281.         end
  282.         core.callbacks:Fire("Post_Sort", true)
  283.     end
  284.     self:RawHookScript(CalendarViewEventInviteListStatusSortButton, "OnClick", StatusSortButtonOverride)
  285.     self:RawHookScript(CalendarCreateEventInviteListStatusSortButton, "OnClick", StatusSortButtonOverride)
  286.  
  287.     -- Register our context menu entry
  288.     core:NewContextMenuEntry({
  289.         text = "Set Role",
  290.         subMenu = "CalendarRoleContextMenu",
  291.     })
  292. end
  293.  
  294.  --[[ -------- Hooks -------- ]]--
  295.  
  296. -- CalendarEventGetInvite() hook, gets the real player index from our reSortedList table
  297. function module.CalendarEventGetInvite(orig, ...)
  298.     if overrideSort then
  299.         local index = ...
  300.         if sortReverse then
  301.             index = #module.reSortedList - index + 1
  302.         end
  303.         if index and module.reSortedList[index] then
  304.             return orig(module.reSortedList[index])
  305.         end
  306.     end
  307.     return orig(...)
  308. end
  309.  
  310. function module:CalendarEventInviteList_AnchorSortButtons(inviteList)
  311.     local scrollFrame = inviteList.scrollFrame
  312.     if not scrollFrame or not scrollFrame.buttons or not scrollFrame.buttons[1] then return end
  313.     local inviteButtonName = scrollFrame.buttons[1]:GetName()
  314.  
  315.     local nameSortButton = inviteList.sortButtons.name
  316.     if inviteList.partyMode then
  317.         nameSortButton:SetPoint("LEFT", _G[inviteButtonName.."Name"], "LEFT")
  318.     else
  319.         nameSortButton:SetPoint("LEFT", _G[inviteButtonName.."PartyIcon"], "LEFT")
  320.     end
  321.  
  322.     local classSortButton = inviteList.sortButtons.class
  323.     classSortButton:SetPoint("RIGHT", _G[inviteButtonName.."Class"], "RIGHT")
  324.  
  325.     local statusSortButton = inviteList.sortButtons.status
  326.     statusSortButton:SetPoint("RIGHT", _G[inviteButtonName.."Status"], "RIGHT")
  327.  
  328.     local roleSortButton = inviteList.sortButtons.role
  329.     roleSortButton:SetPoint("RIGHT", _G[inviteButtonName.."Role"], "RIGHT")
  330. end
  331.  
  332. function module:CalendarEventGetInviteSortCriterion()
  333.     if overrideSort then
  334.         return overrideSort, sortReverse
  335.     else
  336.         return self.hooks.CalendarEventGetInviteSortCriterion()
  337.     end
  338. end
  339.  
  340.  --[[ ------ Context Menu ------ ]]--
  341.  
  342. do
  343.     local roleContextMenu = CreateFrame("Frame", "CalendarRoleContextMenu", CalendarContextMenu, "UIMenuTemplate")
  344.     roleContextMenu:Hide()
  345.     roleContextMenu:SetFrameStrata("FULLSCREEN")
  346.     roleContextMenu:EnableMouse(true)
  347.     roleContextMenu:SetScript("OnShow", function(self)
  348.         self:Initialize()
  349.     end)
  350.     roleContextMenu:SetScript("OnEvent", function(self, event)
  351.         if event == "CALENDAR_UPDATE_EVENT" then
  352.             if self:IsShown() then
  353.                 self:Initialize()
  354.             end
  355.         end
  356.     end)
  357.     roleContextMenu:SetBackdropBorderColor(TOOLTIP_DEFAULT_COLOR.r, TOOLTIP_DEFAULT_COLOR.g, TOOLTIP_DEFAULT_COLOR.b)
  358.     roleContextMenu:SetBackdropColor(TOOLTIP_DEFAULT_BACKGROUND_COLOR.r, TOOLTIP_DEFAULT_BACKGROUND_COLOR.g, TOOLTIP_DEFAULT_BACKGROUND_COLOR.b)
  359.     roleContextMenu:RegisterEvent("CALENDAR_UPDATE_EVENT")
  360.     roleContextMenu.parentMenu = "CalendarContextMenu"
  361.  
  362.     function roleContextMenu:Initialize()
  363.         UIMenu_Initialize(self)
  364.  
  365.         local name = CalendarEventGetInvite(CalendarContextMenu.inviteButton.inviteIndex)
  366.  
  367.         for k, v in ipairs(roleIndexToName) do
  368.             if v == "?" then
  369.                 UIMenu_AddButton(self)
  370.             end
  371.             UIMenu_AddButton(
  372.                 self,                   -- menu
  373.                 v == "Heal" and "Healer" or v == "?" and "Clear" or v, -- text
  374.                 nil,                    -- shortcut
  375.                 self.SetRole,           -- func
  376.                 nil,                    -- nested
  377.                 {name = name, role = k} -- value
  378.             )
  379.         end
  380.  
  381.         return UIMenu_FinishInitializing(self)
  382.     end
  383.  
  384.     function roleContextMenu:SetRole()
  385.         -- If the mass-select module is there and loaded, set the roles using it instead
  386.         if massSelectModule then
  387.             massSelectModule:RunOnSelected(function(...) module:SetRole(...) end, true, self.value.role)
  388.         else
  389.             module:SetRole(self.value.name, self.value.role)
  390.         end
  391.  
  392.         -- Todo: Don't we need to mark the list dirty now?
  393.         core:UpdateOpenList()
  394.         CalendarContextMenu_Hide()
  395.     end
  396. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement