LFGList.lua

LFGList.lua (9.0.2.37176; unchanged since 9.0.2.36949)
  1. -------------------------------------------------------
  2. ----------Constants
  3. -------------------------------------------------------
  4. MAX_LFG_LIST_APPLICATIONS = 5;
  5. MAX_LFG_LIST_SEARCH_AUTOCOMPLETE_ENTRIES = 6;
  6. MAX_LFG_LIST_GROUP_DROPDOWN_ENTRIES = 17;
  7. LFG_LIST_DELISTED_FONT_COLOR = {r=0.3, g=0.3, b=0.3};
  8. LFG_LIST_COMMENT_FONT_COLOR = {r=0.6, g=0.6, b=0.6};
  9. GROUP_FINDER_CATEGORY_ID_DUNGEONS = 2;
  10. ACTIVITY_RETURN_VALUES = {
  11. fullName = 1,
  12. shortName = 2,
  13. categoryID = 3,
  14. groupID = 4,
  15. itemLevel = 5,
  16. filters = 6,
  17. minLevel = 7,
  18. maxPlayers = 8,
  19. displayType = 9,
  20. orderIndex = 10,
  21. useHonorLevel = 11,
  22. };
  23. --Hard-coded values. Should probably make these part of the DB, but it gets a little more complicated with the per-expansion textures
  24. LFG_LIST_CATEGORY_TEXTURES = {
  25. [1] = "questing",
  26. [2] = "dungeons",
  27. [3] = "raids", --Prefix for expansion
  28. [4] = "arenas",
  29. [5] = "scenarios",
  30. [6] = "custom", -- Prefix for "-pve" or "-pvp"
  31. [7] = "skirmishes",
  32. [8] = "battlegrounds",
  33. [9] = "ratedbgs",
  34. [10] = "ashran",
  35. [111] = "islands",
  36. [113] = "torghast",
  37. };
  38. LFG_LIST_PER_EXPANSION_TEXTURES = {
  39. [0] = "classic",
  40. [1] = "bc",
  41. [2] = "wrath",
  42. [3] = "cataclysm",
  43. [4] = "mists",
  44. [5] = "warlords",
  45. [6] = "legion",
  46. [7] = "battleforazeroth",
  47. [8] = "shadowlands",
  48. }
  49. LFG_LIST_GROUP_DATA_ATLASES = {
  50. --Roles
  51. TANK = "groupfinder-icon-role-large-tank",
  52. HEALER = "groupfinder-icon-role-large-heal",
  53. DAMAGER = "groupfinder-icon-role-large-dps",
  54. };
  55. --Fill out classes
  56. for i=1, #CLASS_SORT_ORDER do
  57. LFG_LIST_GROUP_DATA_ATLASES[CLASS_SORT_ORDER[i]] = "groupfinder-icon-class-"..string.lower(CLASS_SORT_ORDER[i]);
  58. end
  59. LFG_LIST_GROUP_DATA_ROLE_ORDER = { "TANK", "HEALER", "DAMAGER" };
  60. LFG_LIST_GROUP_DATA_CLASS_ORDER = CLASS_SORT_ORDER;
  61. StaticPopupDialogs["LFG_LIST_INVITING_CONVERT_TO_RAID"] = {
  62. text = LFG_LIST_CONVERT_TO_RAID_WARNING,
  63. button1 = INVITE,
  64. button2 = CANCEL,
  65. OnAccept = function(self, applicantID) C_PartyInfo.ConfirmConvertToRaid(); C_LFGList.InviteApplicant(applicantID) end,
  66. timeout = 0,
  67. whileDead = 1,
  68. hideOnEscape = 1,
  69. }
  70. local function ResolveCategoryFilters(categoryID, filters)
  71. -- Dungeons ONLY display recommended groups.
  72. if categoryID == GROUP_FINDER_CATEGORY_ID_DUNGEONS then
  73. return bit.band(bit.bnot(LE_LFG_LIST_FILTER_NOT_RECOMMENDED), bit.bor(filters, LE_LFG_LIST_FILTER_RECOMMENDED));
  74. end
  75. return filters;
  76. end
  77. local function GetStartGroupRestriction()
  78. if ( C_SocialRestrictions.IsSilenced() ) then
  79. return "SILENCED", RED_FONT_COLOR:WrapTextInColorCode(ERR_ACCOUNT_SILENCED);
  80. elseif ( C_SocialRestrictions.IsSquelched() ) then
  81. return "SQUELCHED", RED_FONT_COLOR:WrapTextInColorCode(ERR_USER_SQUELCHED);
  82. end
  83. return nil, nil;
  84. end
  85. -------------------------------------------------------
  86. ----------Base Frame
  87. -------------------------------------------------------
  88. LFG_LIST_EDIT_BOX_TAB_CATEGORIES = {};
  89. function LFGListFrame_OnLoad(self)
  90. self:RegisterEvent("PARTY_LEADER_CHANGED");
  91. self:RegisterEvent("GROUP_ROSTER_UPDATE");
  92. self:RegisterEvent("PLAYER_SPECIALIZATION_CHANGED");
  93. self:RegisterEvent("PLAYER_ROLES_ASSIGNED");
  94. self:RegisterEvent("TRIAL_STATUS_UPDATE");
  95. self:RegisterEvent("LFG_LIST_AVAILABILITY_UPDATE");
  96. self:RegisterEvent("LFG_LIST_ACTIVE_ENTRY_UPDATE");
  97. self:RegisterEvent("LFG_LIST_ENTRY_CREATION_FAILED");
  98. self:RegisterEvent("LFG_LIST_SEARCH_RESULTS_RECEIVED");
  99. self:RegisterEvent("LFG_LIST_SEARCH_RESULT_UPDATED");
  100. self:RegisterEvent("LFG_LIST_SEARCH_FAILED");
  101. self:RegisterEvent("LFG_LIST_APPLICANT_LIST_UPDATED");
  102. self:RegisterEvent("LFG_LIST_APPLICANT_UPDATED");
  103. self:RegisterEvent("LFG_LIST_ENTRY_EXPIRED_TOO_MANY_PLAYERS");
  104. self:RegisterEvent("LFG_LIST_ENTRY_EXPIRED_TIMEOUT");
  105. self:RegisterEvent("LFG_LIST_APPLICATION_STATUS_UPDATED");
  106. self:RegisterEvent("UNIT_CONNECTION");
  107. self:RegisterEvent("LFG_GROUP_DELISTED_LEADERSHIP_CHANGE");
  108. for i=1, #LFG_LIST_ACTIVE_QUEUE_MESSAGE_EVENTS do
  109. self:RegisterEvent(LFG_LIST_ACTIVE_QUEUE_MESSAGE_EVENTS[i]);
  110. end
  111. LFGListFrame_SetBaseFilters(self, LE_LFG_LIST_FILTER_PVE);
  112. LFGListFrame_SetActivePanel(self, self.NothingAvailable);
  113. self.EventsInBackground = {
  114. LFG_LIST_SEARCH_FAILED = { self.SearchPanel };
  115. };
  116. end
  117. function LFGListFrame_OnEvent(self, event, ...)
  118. if ( event == "LFG_LIST_AVAILABILITY_UPDATE" or event == "TRIAL_STATUS_UPDATE") then
  119. LFGListFrame_FixPanelValid(self);
  120. elseif ( event == "LFG_LIST_ACTIVE_ENTRY_UPDATE" ) then
  121. local createdNew = ...;
  122. LFGListFrame_FixPanelValid(self); --If our current panel isn't valid, change it.
  123. if ( C_LFGList.HasActiveEntryInfo() ) then
  124. self.EntryCreation.WorkingCover:Hide();
  125. else
  126. LFGListFrame_CheckPendingQuestIDSearch(self);
  127. end
  128. if ( createdNew ) then
  129. PlaySound(SOUNDKIT.PVP_ENTER_QUEUE);
  130. end
  131. elseif ( event == "LFG_LIST_ENTRY_CREATION_FAILED" ) then
  132. self.EntryCreation.WorkingCover:Hide();
  133. elseif ( event == "LFG_LIST_APPLICANT_LIST_UPDATED" ) then
  134. local hasNewPending, hasNewPendingWithData = ...;
  135. if ( hasNewPending and hasNewPendingWithData and LFGListUtil_IsEntryEmpowered() ) then
  136. local isLeader = UnitIsGroupLeader("player", LE_PARTY_CATEGORY_HOME);
  137. local activeEntryInfo = C_LFGList.GetActiveEntryInfo();
  138. local numPings = nil;
  139. if ( not isLeader ) then
  140. numPings = 6;
  141. end
  142. --Non-leaders don't get another ping until they open the panel or we reset the count to 0
  143. if ( isLeader or not self.stopAssistPings ) then
  144. if ( activeEntryInfo.autoAccept ) then
  145. --Check if we would be auto-inviting more people if we were in a raid
  146. if ( not IsInRaid(LE_PARTY_CATEGORY_HOME) and
  147. GetNumGroupMembers(LE_PARTY_CATEGORY_HOME) + C_LFGList.GetNumInvitedApplicantMembers() + C_LFGList.GetNumPendingApplicantMembers() > (MAX_PARTY_MEMBERS+1) ) then
  148. if ( self.displayedAutoAcceptConvert ) then
  149. QueueStatusMinimapButton_SetGlowLock(QueueStatusMinimapButton, "lfglist-applicant", true, numPings);
  150. self.stopAssistPings = true;
  151. else
  152. self.displayedAutoAcceptConvert = true;
  153. StaticPopup_Show("LFG_LIST_AUTO_ACCEPT_CONVERT_TO_RAID");
  154. end
  155. end
  156. elseif ( not self:IsVisible() ) then
  157. QueueStatusMinimapButton_SetGlowLock(QueueStatusMinimapButton, "lfglist-applicant", true, numPings);
  158. self.stopAssistPings = true;
  159. end
  160. end
  161. end
  162. elseif ( event == "LFG_LIST_APPLICANT_UPDATED" ) then
  163. local numApps, numActiveApps = C_LFGList.GetNumApplicants();
  164. if ( numActiveApps == 0 ) then
  165. QueueStatusMinimapButton_SetGlowLock(QueueStatusMinimapButton, "lfglist-applicant", false);
  166. self.stopAssistPings = false;
  167. end
  168. elseif ( event == "LFG_LIST_ENTRY_EXPIRED_TOO_MANY_PLAYERS" ) then
  169. if ( UnitIsGroupLeader("player", LE_PARTY_CATEGORY_HOME) ) then
  170. StaticPopup_Show("LFG_LIST_ENTRY_EXPIRED_TOO_MANY_PLAYERS");
  171. end
  172. elseif ( event == "LFG_LIST_ENTRY_EXPIRED_TIMEOUT" ) then
  173. if ( UnitIsGroupLeader("player", LE_PARTY_CATEGORY_HOME) ) then
  174. StaticPopup_Show("LFG_LIST_ENTRY_EXPIRED_TIMEOUT");
  175. end
  176. elseif ( event == "LFG_LIST_APPLICATION_STATUS_UPDATED" ) then
  177. local searchResultID, newStatus, oldStatus, kstringGroupName = ...;
  178. local chatMessage = LFGListFrame_GetChatMessageForSearchStatusChange(newStatus);
  179. if ( chatMessage ) then
  180. ChatFrame_DisplaySystemMessageInPrimary(chatMessage:format(kstringGroupName));
  181. end
  182. elseif ( event == "GROUP_ROSTER_UPDATE" ) then
  183. if ( not IsInGroup(LE_PARTY_CATEGORY_HOME) ) then
  184. self.displayedAutoAcceptConvert = false;
  185. end
  186. elseif ( event == "LFG_GROUP_DELISTED_LEADERSHIP_CHANGE") then
  187. local listingTitle, delistTime = ...;
  188. StaticPopup_Show("PREMADE_GROUP_LEADER_CHANGE_DELIST_WARNING", nil, nil, { listingTitle = listingTitle, delistTime = delistTime, });
  189. end
  190. --Dispatch the event to our currently active panel
  191. local onEvent = self.activePanel and self.activePanel:GetScript("OnEvent");
  192. if ( onEvent ) then
  193. onEvent(self.activePanel, event, ...);
  194. end
  195. --Dispatch the event to any panels that want the event in the background
  196. local bg = self.EventsInBackground[event];
  197. if ( bg ) then
  198. for i=1, #bg do
  199. if ( bg[i] ~= self.activePanel ) then
  200. bg[i]:GetScript("OnEvent")(bg[i], event, ...);
  201. end
  202. end
  203. end
  204. end
  205. function LFGListFrame_OnShow(self)
  206. LFGListFrame_FixPanelValid(self);
  207. C_LFGList.RequestAvailableActivities();
  208. self.stopAssistPings = false;
  209. QueueStatusMinimapButton_SetGlowLock(QueueStatusMinimapButton, "lfglist-applicant", false);
  210. PlaySound(SOUNDKIT.IG_CHARACTER_INFO_OPEN);
  211. end
  212. function LFGListFrame_OnHide(self)
  213. LFGListFrame_SetPendingQuestIDSearch(self, nil);
  214. LFGListEntryCreation_ClearAutoCreateMode(self.EntryCreation);
  215. self.SearchPanel.shouldAlwaysShowCreateGroupButton = nil;
  216. end
  217. function LFGListFrame_GetChatMessageForSearchStatusChange(newStatus)
  218. if ( newStatus == "declined" ) then
  219. return LFG_LIST_APP_DECLINED_MESSAGE;
  220. elseif ( newStatus == "declined_full" ) then
  221. return LFG_LIST_APP_DECLINED_FULL_MESSAGE;
  222. elseif ( newStatus == "declined_delisted" ) then
  223. return LFG_LIST_APP_DECLINED_DELISTED_MESSAGE;
  224. elseif ( newStatus == "timedout" ) then
  225. return LFG_LIST_APP_TIMED_OUT_MESSAGE;
  226. end
  227. end
  228. function LFGListFrame_SetActivePanel(self, panel)
  229. if ( self.activePanel ) then
  230. self.activePanel:Hide();
  231. end
  232. self.activePanel = panel;
  233. self.activePanel:Show();
  234. end
  235. function LFGListFrame_IsPanelValid(self, panel)
  236. local listed = C_LFGList.HasActiveEntryInfo();
  237. --If we're listed, make sure we're either viewing applicants or editing our group
  238. if ( listed and panel ~= self.ApplicationViewer and not (panel == self.EntryCreation and LFGListEntryCreation_IsEditMode(self.EntryCreation)) ) then
  239. return false;
  240. end
  241. --If we're not listed, we can't be viewing applicants or editing our group
  242. if ( not listed and (panel == self.ApplicationViewer or
  243. (panel == self.EntryCreation and LFGListEntryCreation_IsEditMode(self.EntryCreation)) ) ) then
  244. return false;
  245. end
  246. --Make sure we aren't creating a new entry with different baseFilters
  247. if ( panel == self.EntryCreation ) then
  248. if ( not LFGListEntryCreation_IsEditMode(self.EntryCreation) and self.baseFilters ~= self.EntryCreation.baseFilters ) then
  249. return false;
  250. end
  251. end
  252. --Make sure we aren't searching with different baseFilters
  253. if ( panel == self.SearchPanel ) then
  254. if ( self.baseFilters ~= self.SearchPanel.preferredFilters ) then
  255. return false;
  256. end
  257. end
  258. --If we're a trial account, we can only see the NothingAvailable and ApplicationViewer
  259. if ( IsRestrictedAccount() ) then
  260. if ( panel ~= self.NothingAvailable and panel ~= self.ApplicationViewer ) then
  261. return false;
  262. end
  263. end
  264. --If we don't have any available activities, say so
  265. if ( #C_LFGList.GetAvailableCategories(self.baseFilters) == 0 ) then
  266. if ( panel == self.CategorySelection ) then
  267. return false;
  268. end
  269. else
  270. if ( panel == self.NothingAvailable and not IsRestrictedAccount() ) then
  271. return false;
  272. end
  273. end
  274. return true;
  275. end
  276. function LFGListFrame_GetBestPanel(self)
  277. local listed = C_LFGList.HasActiveEntryInfo();
  278. if ( listed ) then
  279. return self.ApplicationViewer;
  280. elseif ( IsRestrictedAccount() ) then
  281. return self.NothingAvailable;
  282. elseif ( #C_LFGList.GetAvailableCategories(self.baseFilters) == 0 ) then
  283. return self.NothingAvailable;
  284. else
  285. return self.CategorySelection;
  286. end
  287. end
  288. function LFGListFrame_FixPanelValid(self)
  289. if ( not LFGListFrame_IsPanelValid(self, self.activePanel) ) then
  290. LFGListFrame_SetActivePanel(self, LFGListFrame_GetBestPanel(self));
  291. end
  292. end
  293. function LFGListFrame_SetBaseFilters(self, filters)
  294. self.baseFilters = filters;
  295. --If we need to change panels, do so
  296. LFGListFrame_FixPanelValid(self);
  297. --Update the current panel
  298. if ( self.activePanel and self.activePanel.updateAll ) then
  299. self.activePanel.updateAll(self.activePanel);
  300. end
  301. end
  302. function LFGListFrame_CheckPendingQuestIDSearch(self)
  303. local questID = LFGListFrame_GetPendingQuestIDSearch(self);
  304. if questID and not C_LFGList.HasActiveEntryInfo() then
  305. LFGListFrame_SetPendingQuestIDSearch(self, nil);
  306. if issecure() then
  307. LFGListFrame_BeginFindQuestGroup(self, questID);
  308. else
  309. StaticPopup_Show("PREMADE_GROUP_INSECURE_SEARCH", QuestUtils_GetQuestName(questID), nil, questID);
  310. end
  311. end
  312. end
  313. function LFGListFrame_GetPendingQuestIDSearch(self)
  314. return self.pendingQuestIDSearch;
  315. end
  316. function LFGListFrame_SetPendingQuestIDSearch(self, questID)
  317. self.pendingQuestIDSearch = questID;
  318. end
  319. function LFGListFrame_BeginFindQuestGroup(self, questID, shouldShowCreateGroupButton)
  320. local activityID, categoryID, filters, questName = LFGListUtil_GetQuestCategoryData(questID);
  321. if not activityID then
  322. return;
  323. end
  324. if C_LFGList.HasActiveEntryInfo() then
  325. if LFGListUtil_CanListGroup() then
  326. C_LFGList.RemoveListing();
  327. LFGListFrame_SetPendingQuestIDSearch(self, questID);
  328. end
  329. return;
  330. end
  331. self.SearchPanel.shouldAlwaysShowCreateGroupButton = shouldShowCreateGroupButton;
  332. PVEFrame_ShowFrame("GroupFinderFrame", LFGListPVEStub);
  333. local panel = self.CategorySelection;
  334. LFGListCategorySelection_SelectCategory(panel, categoryID, filters);
  335. LFGListCategorySelection_StartFindGroup(panel, questID);
  336. LFGListEntryCreation_SetAutoCreateMode(panel:GetParent().EntryCreation, "quest", activityID, questID);
  337. end
  338. -------------------------------------------------------
  339. ----------Nothing available frame
  340. -------------------------------------------------------
  341. function LFGListNothingAvailable_OnEvent(self, event, ...)
  342. --Note: events are dispatched from the base frame. Add RegisterEvent there.
  343. if ( event == "LFG_LIST_AVAILABILITY_UPDATE" ) then
  344. LFGListNothingAvailable_Update(self);
  345. end
  346. end
  347. function LFGListNothingAvailable_Update(self)
  348. if ( IsRestrictedAccount() ) then
  349. self.Label:SetText(ERR_RESTRICTED_ACCOUNT_LFG_LIST_TRIAL);
  350. elseif ( C_LFGList.HasActivityList() ) then
  351. self.Label:SetText(NO_LFG_LIST_AVAILABLE);
  352. else
  353. self.Label:SetText(LFG_LIST_LOADING);
  354. end
  355. end
  356. -------------------------------------------------------
  357. ----------Category selection
  358. -------------------------------------------------------
  359. function LFGListCategorySelection_OnLoad(self)
  360. LFGListCategorySelection_UpdateNavButtons(self);
  361. end
  362. function LFGListCategorySelection_OnEvent(self, event, ...)
  363. --Note: events are dispatched from the base frame. Add RegisterEvent there.
  364. if ( event == "LFG_LIST_AVAILABILITY_UPDATE" ) then
  365. LFGListCategorySelection_UpdateCategoryButtons(self);
  366. end
  367. if ( tContains(LFG_LIST_ACTIVE_QUEUE_MESSAGE_EVENTS, event) ) then
  368. LFGListCategorySelection_UpdateNavButtons(self);
  369. end
  370. end
  371. function LFGListCategorySelection_OnShow(self)
  372. LFGListCategorySelection_UpdateCategoryButtons(self);
  373. LFGListCategorySelection_UpdateNavButtons(self);
  374. end
  375. function LFGListCategorySelection_UpdateCategoryButtons(self)
  376. local baseFilters = self:GetParent().baseFilters;
  377. local categories = C_LFGList.GetAvailableCategories(baseFilters);
  378. local nextBtn = 1;
  379. local hasSelected = false;
  380. --Update category buttons
  381. for i=1, #categories do
  382. local isSelected = false;
  383. local categoryID = categories[i];
  384. local name, separateRecommended = C_LFGList.GetCategoryInfo(categoryID);
  385. if ( separateRecommended ) then
  386. nextBtn, isSelected = LFGListCategorySelection_AddButton(self, nextBtn, categoryID, LE_LFG_LIST_FILTER_RECOMMENDED);
  387. hasSelected = hasSelected or isSelected;
  388. nextBtn, isSelected = LFGListCategorySelection_AddButton(self, nextBtn, categoryID, LE_LFG_LIST_FILTER_NOT_RECOMMENDED);
  389. else
  390. nextBtn, isSelected = LFGListCategorySelection_AddButton(self, nextBtn, categoryID, 0);
  391. end
  392. hasSelected = hasSelected or isSelected;
  393. end
  394. --Hide any extra buttons
  395. for i=nextBtn, #self.CategoryButtons do
  396. self.CategoryButtons[i]:Hide();
  397. end
  398. --If the selected item isn't in the list, deselect it
  399. if ( self.selectedCategory and not hasSelected ) then
  400. LFGListCategorySelection_SelectCategory(self, nil, nil);
  401. end
  402. end
  403. function LFGListCategorySelection_AddButton(self, btnIndex, categoryID, filters)
  404. --Check that we have activities with this filter
  405. local baseFilters = self:GetParent().baseFilters;
  406. local allFilters = bit.bor(baseFilters, filters);
  407. if ( filters ~= 0 and #C_LFGList.GetAvailableActivities(categoryID, nil, allFilters) == 0) then
  408. return btnIndex, false;
  409. end
  410. local name, separateRecommended = C_LFGList.GetCategoryInfo(categoryID);
  411. local button = self.CategoryButtons[btnIndex];
  412. if ( not button ) then
  413. self.CategoryButtons[btnIndex] = CreateFrame("BUTTON", nil, self, "LFGListCategoryTemplate");
  414. self.CategoryButtons[btnIndex]:SetPoint("TOP", self.CategoryButtons[btnIndex - 1], "BOTTOM", 0, -3);
  415. button = self.CategoryButtons[btnIndex];
  416. end
  417. button:SetText(LFGListUtil_GetDecoratedCategoryName(name, filters, true));
  418. button.categoryID = categoryID;
  419. button.filters = filters;
  420. local atlasName = nil;
  421. if ( bit.band(allFilters, LE_LFG_LIST_FILTER_RECOMMENDED) ~= 0 ) then
  422. atlasName = "groupfinder-button-"..(LFG_LIST_CATEGORY_TEXTURES[categoryID] or "raids").."-"..LFG_LIST_PER_EXPANSION_TEXTURES[LFGListUtil_GetCurrentExpansion()];
  423. elseif ( bit.band(allFilters, LE_LFG_LIST_FILTER_NOT_RECOMMENDED) ~= 0 ) then
  424. atlasName = "groupfinder-button-"..(LFG_LIST_CATEGORY_TEXTURES[categoryID] or "raids").."-"..LFG_LIST_PER_EXPANSION_TEXTURES[math.max(0,LFGListUtil_GetCurrentExpansion() - 1)];
  425. else
  426. atlasName = "groupfinder-button-"..(LFG_LIST_CATEGORY_TEXTURES[categoryID] or "questing");
  427. end
  428. local suffix = "";
  429. if ( bit.band(allFilters, LE_LFG_LIST_FILTER_PVE) ~= 0 ) then
  430. suffix = "-pve";
  431. elseif ( bit.band(allFilters, LE_LFG_LIST_FILTER_PVP) ~= 0 ) then
  432. suffix = "-pvp";
  433. end
  434. --Try with the suffix and then without it
  435. if ( not button.Icon:SetAtlas(atlasName..suffix) ) then
  436. button.Icon:SetAtlas(atlasName);
  437. end
  438. local selected = self.selectedCategory == categoryID and self.selectedFilters == filters;
  439. button.SelectedTexture:SetShown(selected);
  440. button:Show();
  441. return btnIndex + 1, selected;
  442. end
  443. function LFGListCategorySelection_SelectCategory(self, categoryID, filters)
  444. self.selectedCategory = categoryID;
  445. self.selectedFilters = filters;
  446. LFGListCategorySelection_UpdateCategoryButtons(self);
  447. LFGListCategorySelection_UpdateNavButtons(self);
  448. end
  449. function LFGListCategorySelection_UpdateNavButtons(self)
  450. local findEnabled, startEnabled = true, true;
  451. self.FindGroupButton.tooltip = nil;
  452. self.StartGroupButton.tooltip = nil;
  453. --Check if the user needs to select a category
  454. if ( not self.selectedCategory ) then
  455. findEnabled = false;
  456. self.FindGroupButton.tooltip = LFG_LIST_SELECT_A_CATEGORY;
  457. startEnabled = false;
  458. self.StartGroupButton.tooltip = LFG_LIST_SELECT_A_CATEGORY;
  459. end
  460. --Check if the user can't start a group due to not being a leader
  461. if ( IsInGroup(LE_PARTY_CATEGORY_HOME) and not UnitIsGroupLeader("player", LE_PARTY_CATEGORY_HOME) ) then
  462. startEnabled = false;
  463. self.StartGroupButton.tooltip = LFG_LIST_NOT_LEADER;
  464. end
  465. --Check if the player is currently in some incompatible queue
  466. local messageStart = LFGListUtil_GetActiveQueueMessage(false);
  467. if ( messageStart ) then
  468. startEnabled = false;
  469. self.StartGroupButton.tooltip = messageStart;
  470. end
  471. local startError, errorText = GetStartGroupRestriction();
  472. if ( startError ~= nil ) then
  473. startEnabled = false;
  474. self.StartGroupButton.tooltip = errorText;
  475. end
  476. self.FindGroupButton:SetEnabled(findEnabled);
  477. self.StartGroupButton:SetEnabled(startEnabled);
  478. end
  479. function LFGListCategorySelectionStartGroupButton_OnClick(self)
  480. local panel = self:GetParent();
  481. if ( not panel.selectedCategory ) then
  482. return;
  483. end
  484. PlaySound(SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_ON);
  485. local baseFilters = panel:GetParent().baseFilters;
  486. local entryCreation = panel:GetParent().EntryCreation;
  487. LFGListEntryCreation_Show(entryCreation, baseFilters, panel.selectedCategory, panel.selectedFilters);
  488. end
  489. function LFGListCategorySelectionFindGroupButton_OnClick(self)
  490. local panel = self:GetParent();
  491. if ( not panel.selectedCategory ) then
  492. return;
  493. end
  494. PlaySound(SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_ON);
  495. LFGListCategorySelection_StartFindGroup(panel);
  496. end
  497. function LFGListCategorySelection_StartFindGroup(self, questID)
  498. local baseFilters = self:GetParent().baseFilters;
  499. local searchPanel = self:GetParent().SearchPanel;
  500. LFGListSearchPanel_Clear(searchPanel);
  501. if questID then
  502. C_LFGList.SetSearchToQuestID(questID);
  503. end
  504. LFGListSearchPanel_SetCategory(searchPanel, self.selectedCategory, self.selectedFilters, baseFilters);
  505. LFGListSearchPanel_DoSearch(searchPanel);
  506. LFGListFrame_SetActivePanel(self:GetParent(), searchPanel);
  507. end
  508. --The individual category buttons
  509. function LFGListCategorySelectionButton_OnClick(self)
  510. local panel = self:GetParent();
  511. PlaySound(SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_ON);
  512. LFGListCategorySelection_SelectCategory(panel, self.categoryID, self.filters);
  513. LFGListEntryCreation_ClearAutoCreateMode(panel:GetParent().EntryCreation);
  514. end
  515. -------------------------------------------------------
  516. ----------List Entry Creation
  517. -------------------------------------------------------
  518. function LFGListEntryCreation_OnLoad(self)
  519. self.Name.Instructions:SetText(LFG_LIST_ENTER_NAME);
  520. self.Description.EditBox:SetScript("OnEnterPressed", nop);
  521. LFGListUtil_SetUpDropDown(self, self.CategoryDropDown, LFGListEntryCreation_PopulateCategories, LFGListEntryCreation_OnCategorySelected);
  522. LFGListUtil_SetUpDropDown(self, self.GroupDropDown, LFGListEntryCreation_PopulateGroups, LFGListEntryCreation_OnGroupSelected);
  523. LFGListUtil_SetUpDropDown(self, self.ActivityDropDown, LFGListEntryCreation_PopulateActivities, LFGListEntryCreation_OnActivitySelected);
  524. LFGListEntryCreation_SetBaseFilters(self, 0);
  525. end
  526. function LFGListEntryCreation_OnEvent(self, event, ...)
  527. if ( event == "GROUP_ROSTER_UPDATE" ) then
  528. LFGListEntryCreation_UpdateValidState(self);
  529. elseif ( tContains(LFG_LIST_ACTIVE_QUEUE_MESSAGE_EVENTS, event) ) then
  530. LFGListEntryCreation_UpdateValidState(self);
  531. end
  532. end
  533. function LFGListEntryCreation_OnShow(self)
  534. LFGListEntryCreation_UpdateValidState(self);
  535. end
  536. function LFGListEntryCreation_Show(self, baseFilters, selectedCategory, selectedFilters)
  537. --If this was what the player selected last time, just leave it filled out with the same info.
  538. --Also don't save it for categories that try to set it to the current area.
  539. local _, _, _, preferCurrentArea = C_LFGList.GetCategoryInfo(selectedCategory);
  540. local keepOldData = not preferCurrentArea and self.selectedCategory == selectedCategory and baseFilters == self.baseFilters and self.selectedFilters == selectedFilters;
  541. LFGListEntryCreation_SetBaseFilters(self, baseFilters);
  542. if ( not keepOldData ) then
  543. LFGListEntryCreation_Clear(self);
  544. LFGListEntryCreation_Select(self, selectedFilters, selectedCategory);
  545. end
  546. LFGListEntryCreation_SetEditMode(self, false);
  547. LFGListEntryCreation_UpdateValidState(self);
  548. LFGListFrame_SetActivePanel(self:GetParent(), self);
  549. self.Name:SetFocus();
  550. LFGListEntryCreation_CheckAutoCreate(self);
  551. end
  552. function LFGListEntryCreation_Clear(self)
  553. --Clear selections
  554. self.selectedCategory = nil;
  555. self.selectedGroup = nil;
  556. self.selectedActivity = nil;
  557. self.selectedFilters = nil;
  558. --Reset widgets
  559. C_LFGList.ClearCreationTextFields();
  560. self.ItemLevel.CheckButton:SetChecked(false);
  561. self.ItemLevel.EditBox:SetText("");
  562. self.HonorLevel.CheckButton:SetChecked(false);
  563. self.HonorLevel.EditBox:SetText("");
  564. self.VoiceChat.CheckButton:SetChecked(false);
  565. --self.VoiceChat.EditBox:SetText(""); --Cleared in ClearCreationTextFields
  566. self.PrivateGroup.CheckButton:SetChecked(false);
  567. self.ActivityFinder:Hide();
  568. end
  569. function LFGListEntryCreation_ClearFocus(self)
  570. self.Name:ClearFocus();
  571. self.ItemLevel.EditBox:ClearFocus();
  572. self.HonorLevel.EditBox:ClearFocus();
  573. self.VoiceChat.EditBox:ClearFocus();
  574. self.Description.EditBox:ClearFocus();
  575. end
  576. --This function accepts any or all of categoryID, groupId, and activityID
  577. function LFGListEntryCreation_Select(self, filters, categoryID, groupID, activityID)
  578. filters, categoryID, groupID, activityID = LFGListUtil_AugmentWithBest(bit.bor(self.baseFilters,filters or 0), categoryID, groupID, activityID);
  579. self.selectedCategory = categoryID;
  580. self.selectedGroup = groupID;
  581. self.selectedActivity = activityID;
  582. self.selectedFilters = filters;
  583. --Update the category dropdown
  584. local categoryName, _, autoChoose = C_LFGList.GetCategoryInfo(categoryID);
  585. UIDropDownMenu_SetText(self.CategoryDropDown, LFGListUtil_GetDecoratedCategoryName(categoryName, filters, false));
  586. --Update the activity dropdown
  587. local _, shortName, _, _, iLevel, _, _, _, _, _, useHonorLevel = C_LFGList.GetActivityInfo(activityID);
  588. UIDropDownMenu_SetText(self.ActivityDropDown, shortName);
  589. --Update the group dropdown. If the group dropdown is showing an activity, hide the activity dropdown
  590. local groupName = C_LFGList.GetActivityGroupInfo(groupID);
  591. UIDropDownMenu_SetText(self.GroupDropDown, groupName or shortName);
  592. self.ActivityDropDown:SetShown(groupName and not autoChoose);
  593. self.GroupDropDown:SetShown(not autoChoose);
  594. --Update the recommended item level box
  595. if ( iLevel ~= 0 ) then
  596. self.ItemLevel.EditBox.Instructions:SetFormattedText(LFG_LIST_RECOMMENDED_ILVL, iLevel);
  597. else
  598. self.ItemLevel.EditBox.Instructions:SetText(LFG_LIST_ITEM_LEVEL_INSTR_SHORT);
  599. end
  600. if ( useHonorLevel ) then
  601. self.HonorLevel:Show();
  602. self.VoiceChat:SetPoint("TOPLEFT", self.HonorLevel, "BOTTOMLEFT", 0, -3);
  603. else
  604. self.HonorLevel:Hide();
  605. self.VoiceChat:SetPoint("TOPLEFT", self.ItemLevel, "BOTTOMLEFT", 0, -3);
  606. end
  607. LFGListRequirement_Validate(self.ItemLevel, self.ItemLevel.EditBox:GetText());
  608. if ( useHonorLevel ) then
  609. LFGListRequirement_Validate(self.HonorLevel, self.HonorLevel.EditBox:GetText());
  610. end
  611. LFGListEntryCreation_UpdateValidState(self);
  612. end
  613. function LFGListEntryCreation_PopulateCategories(self, dropDown, info)
  614. local categories = C_LFGList.GetAvailableCategories(self.baseFilters);
  615. for i=1, #categories do
  616. local categoryID = categories[i];
  617. local name, separateRecommended = C_LFGList.GetCategoryInfo(categoryID);
  618. if ( separateRecommended ) then
  619. LFGListEntryCreation_AddCategoryEntry(self, info, categoryID, name, LE_LFG_LIST_FILTER_RECOMMENDED);
  620. LFGListEntryCreation_AddCategoryEntry(self, info, categoryID, name, LE_LFG_LIST_FILTER_NOT_RECOMMENDED);
  621. else
  622. LFGListEntryCreation_AddCategoryEntry(self, info, categoryID, name, 0);
  623. end
  624. end
  625. end
  626. function LFGListEntryCreation_AddCategoryEntry(self, info, categoryID, name, filters)
  627. if ( filters ~= 0 and #C_LFGList.GetAvailableActivities(categoryID, nil, filters) == 0 ) then
  628. return;
  629. end
  630. info.text = LFGListUtil_GetDecoratedCategoryName(name, filters, false);
  631. info.value = categoryID;
  632. info.arg1 = filters;
  633. info.checked = (self.selectedCategory == categoryID and self.selectedFilters == filters);
  634. info.isRadio = true;
  635. UIDropDownMenu_AddButton(info);
  636. end
  637. function LFGListEntryCreation_OnCategorySelected(self, categoryID, filters)
  638. LFGListEntryCreation_Select(self, filters, categoryID, nil, nil);
  639. end
  640. function LFGListEntryCreation_PopulateGroups(self, dropDown, info)
  641. if ( not self.selectedCategory ) then
  642. --We don't have a category, so we can't fill out groups.
  643. return;
  644. end
  645. local useMore = false;
  646. --Start out displaying everything
  647. local groups = C_LFGList.GetAvailableActivityGroups(self.selectedCategory, bit.bor(self.baseFilters, self.selectedFilters));
  648. local activities = C_LFGList.GetAvailableActivities(self.selectedCategory, 0, bit.bor(self.baseFilters, self.selectedFilters));
  649. if ( self.selectedFilters == 0 ) then
  650. --We don't bother filtering if we have less than 5 items anyway
  651. if ( #groups + #activities > 5 ) then
  652. --Try just displaying the recommended
  653. local filters = bit.bor(self.selectedFilters, self.baseFilters, LE_LFG_LIST_FILTER_RECOMMENDED);
  654. local recGroups = C_LFGList.GetAvailableActivityGroups(self.selectedCategory, filters);
  655. local recActivities = C_LFGList.GetAvailableActivities(self.selectedCategory, 0, filters);
  656. --If we have some recommended, just display those
  657. if ( #recGroups + #recActivities > 0 ) then
  658. --If we still have just as many, we don't need to display more
  659. useMore = #recGroups ~= #groups or #recActivities ~= #activities;
  660. groups = recGroups;
  661. activities = recActivities;
  662. end
  663. end
  664. end
  665. local groupOrder = groups[1] and select(2, C_LFGList.GetActivityGroupInfo(groups[1]));
  666. local activityOrder = activities[1] and select(10, C_LFGList.GetActivityInfo(activities[1]));
  667. local groupIndex, activityIndex = 1, 1;
  668. --Start merging
  669. for i=1, MAX_LFG_LIST_GROUP_DROPDOWN_ENTRIES do
  670. if ( not groupOrder and not activityOrder ) then
  671. break;
  672. end
  673. if ( activityOrder and (not groupOrder or activityOrder < groupOrder) ) then
  674. local activityID = activities[activityIndex];
  675. local name = select(ACTIVITY_RETURN_VALUES.shortName, C_LFGList.GetActivityInfo(activityID));
  676. info.text = name;
  677. info.value = activityID;
  678. info.arg1 = "activity";
  679. info.checked = (self.selectedActivity == activityID);
  680. info.isRadio = true;
  681. UIDropDownMenu_AddButton(info);
  682. activityIndex = activityIndex + 1;
  683. activityOrder = activities[activityIndex] and select(10, C_LFGList.GetActivityInfo(activities[activityIndex]));
  684. else
  685. local groupID = groups[groupIndex];
  686. local name = C_LFGList.GetActivityGroupInfo(groupID);
  687. info.text = name;
  688. info.value = groupID;
  689. info.arg1 = "group";
  690. info.checked = (self.selectedGroup == groupID);
  691. info.isRadio = true;
  692. UIDropDownMenu_AddButton(info);
  693. groupIndex = groupIndex + 1;
  694. groupOrder = groups[groupIndex] and select(2, C_LFGList.GetActivityGroupInfo(groups[groupIndex]));
  695. end
  696. end
  697. if ( #activities + #groups > MAX_LFG_LIST_GROUP_DROPDOWN_ENTRIES ) then
  698. useMore = true;
  699. end
  700. if ( useMore ) then
  701. info.text = LFG_LIST_MORE;
  702. info.value = nil;
  703. info.arg1 = "more";
  704. info.notCheckable = true;
  705. info.checked = false;
  706. info.isRadio = false;
  707. UIDropDownMenu_AddButton(info);
  708. end
  709. end
  710. function LFGListEntryCreation_OnGroupSelected(self, id, buttonType)
  711. if ( buttonType == "activity" ) then
  712. LFGListEntryCreation_Select(self, nil, nil, nil, id);
  713. elseif ( buttonType == "group" ) then
  714. LFGListEntryCreation_Select(self, self.selectedFilters, self.selectedCategory, id, nil);
  715. elseif ( buttonType == "more" ) then
  716. LFGListEntryCreationActivityFinder_Show(self.ActivityFinder, self.selectedCategory, nil, bit.bor(self.baseFilters, self.selectedFilters));
  717. end
  718. end
  719. function LFGListEntryCreation_PopulateActivities(self, dropDown, info)
  720. local useMore = self.selectedFilters == 0;
  721. local filters = bit.bor(self.baseFilters, self.selectedFilters);
  722. --Start out displaying everything
  723. local activities = C_LFGList.GetAvailableActivities(self.selectedCategory, self.selectedGroup, filters);
  724. --If we're displaying more than 5, see if we can just display recommended
  725. if ( useMore ) then
  726. if ( #activities > 5 ) then
  727. filters = bit.bor(filters, LE_LFG_LIST_FILTER_RECOMMENDED);
  728. local recActivities = C_LFGList.GetAvailableActivities(self.selectedCategory, self.selectedGroup, filters);
  729. useMore = #recActivities ~= #activities;
  730. if ( #recActivities > 0 ) then
  731. activities = recActivities;
  732. else
  733. --Just display up to 5 non-recommended activities
  734. for i=#activities, 5, -1 do
  735. activities[i] = nil;
  736. end
  737. end
  738. else
  739. useMore = false;
  740. end
  741. end
  742. for i=1, #activities do
  743. local activityID = activities[i];
  744. local shortName = select(ACTIVITY_RETURN_VALUES.shortName, C_LFGList.GetActivityInfo(activityID));
  745. info.text = shortName;
  746. info.value = activityID;
  747. info.arg1 = "activity";
  748. info.checked = (self.selectedActivity == activityID);
  749. info.isRadio = true;
  750. UIDropDownMenu_AddButton(info);
  751. end
  752. if ( useMore ) then
  753. info.text = LFG_LIST_MORE;
  754. info.value = nil;
  755. info.arg1 = "more";
  756. info.notCheckable = true;
  757. info.checked = false;
  758. info.isRadio = false;
  759. UIDropDownMenu_AddButton(info);
  760. end
  761. end
  762. function LFGListEntryCreation_OnActivitySelected(self, activityID, buttonType)
  763. if ( buttonType == "activity" ) then
  764. LFGListEntryCreation_Select(self, nil, nil, nil, activityID);
  765. elseif ( buttonType == "more" ) then
  766. LFGListEntryCreationActivityFinder_Show(self.ActivityFinder, self.selectedCategory, self.selectedGroup, bit.bor(self.baseFilters, self.selectedFilters));
  767. end
  768. end
  769. function LFGListEntryCreation_GetSanitizedName(self)
  770. return string.match(self.Name:GetText(), "^%s*(.-)%s*$");
  771. end
  772. function LFGListEntryCreation_ListGroupInternal(self, activityID, itemLevel, honorLevel, autoAccept, privateGroup, questID)
  773. if ( LFGListEntryCreation_IsEditMode(self) ) then
  774. local activeEntryInfo = C_LFGList.GetActiveEntryInfo();
  775. C_LFGList.UpdateListing(activityID, itemLevel, honorLevel, activeEntryInfo.autoAccept, privateGroup, activeEntryInfo.questID);
  776. LFGListFrame_SetActivePanel(self:GetParent(), self:GetParent().ApplicationViewer);
  777. else
  778. if(C_LFGList.CreateListing(activityID, itemLevel, honorLevel, autoAccept, privateGroup, questID)) then
  779. self.WorkingCover:Show();
  780. LFGListEntryCreation_ClearFocus(self);
  781. end
  782. end
  783. end
  784. function LFGListEntryCreation_ListGroup(self)
  785. local itemLevel = tonumber(self.ItemLevel.EditBox:GetText()) or 0;
  786. local honorLevel = tonumber(self.HonorLevel.EditBox:GetText()) or 0;
  787. local autoAccept = false;
  788. local privateGroup = self.PrivateGroup.CheckButton:GetChecked();
  789. LFGListEntryCreation_ListGroupInternal(self, self.selectedActivity, itemLevel, honorLevel, autoAccept, privateGroup);
  790. end
  791. function LFGListEntryCreation_SetAutoCreateDataInternal(self, activityType, activityID, contextID)
  792. self.autoCreateActivityType = activityType;
  793. self.autoCreateActivityID = activityID;
  794. self.autoCreateContextID = contextID;
  795. end
  796. function LFGListEntryCreation_SetAutoCreateMode(self, activityType, activityID, contextID)
  797. LFGListEntryCreation_SetAutoCreateDataInternal(self, activityType, activityID, contextID);
  798. end
  799. function LFGListEntryCreation_ClearAutoCreateMode(self)
  800. LFGListEntryCreation_SetAutoCreateDataInternal(self, nil, nil, nil);
  801. end
  802. function LFGListEntryCreation_IsAutoCreateMode(self)
  803. return self.autoCreateActivityType ~= nil;
  804. end
  805. function LFGListEntryCreation_GetAutoCreateDataQuest(self)
  806. local questID, activityID = self.autoCreateContextID, self.autoCreateActivityID;
  807. local itemLevel = 0;
  808. local honorLevel = 0;
  809. local autoAccept = true;
  810. local privateGroup = false;
  811. return activityID, itemLevel, honorLevel, autoAccept, privateGroup, questID;
  812. end
  813. function LFGListEntryCreation_GetAutoCreateData(self)
  814. if self.autoCreateActivityType == "quest" then
  815. return LFGListEntryCreation_GetAutoCreateDataQuest(self);
  816. end
  817. end
  818. function LFGListEntryCreation_CheckAutoCreate(self)
  819. if LFGListEntryCreation_IsAutoCreateMode(self) then
  820. C_LFGList.ClearCreationTextFields();
  821. LFGListEntryCreation_ListGroupInternal(self, LFGListEntryCreation_GetAutoCreateData(self));
  822. LFGListEntryCreation_ClearAutoCreateMode(self);
  823. end
  824. end
  825. function LFGListEntryCreation_UpdateValidState(self)
  826. local errorText;
  827. local maxPlayers, _, _, useHonorLevel = select(ACTIVITY_RETURN_VALUES.maxPlayers, C_LFGList.GetActivityInfo(self.selectedActivity));
  828. if ( maxPlayers > 0 and GetNumGroupMembers(LE_PARTY_CATEGORY_HOME) >= maxPlayers ) then
  829. errorText = string.format(LFG_LIST_TOO_MANY_FOR_ACTIVITY, maxPlayers);
  830. elseif ( LFGListEntryCreation_GetSanitizedName(self) == "" ) then
  831. errorText = LFG_LIST_MUST_HAVE_NAME;
  832. elseif ( self.ItemLevel.warningText ) then
  833. errorText = self.ItemLevel.warningText;
  834. elseif ( useHonorLevel and self.HonorLevel.warningText ) then
  835. errorText = self.HonorLevel.warningText;
  836. else
  837. errorText = LFGListUtil_GetActiveQueueMessage(false);
  838. end
  839. self.ListGroupButton:SetEnabled(not errorText);
  840. self.ListGroupButton.errorText = errorText;
  841. end
  842. function LFGListEntryCreation_SetBaseFilters(self, baseFilters)
  843. self.baseFilters = baseFilters;
  844. end
  845. function LFGListEntryCreation_SetEditMode(self, editMode)
  846. self.editMode = editMode;
  847. if ( editMode ) then
  848. local activeEntryInfo = C_LFGList.GetActiveEntryInfo();
  849. assert(activeEntryInfo);
  850. --Update the dropdowns
  851. LFGListEntryCreation_Select(self, nil, nil, nil, activeEntryInfo.activityID);
  852. UIDropDownMenu_DisableDropDown(self.CategoryDropDown);
  853. UIDropDownMenu_DisableDropDown(self.GroupDropDown);
  854. UIDropDownMenu_DisableDropDown(self.ActivityDropDown);
  855. --Update edit boxes
  856. C_LFGList.CopyActiveEntryInfoToCreationFields();
  857. self.Name:SetEnabled(activeEntryInfo.questID == nil);
  858. if ( activeEntryInfo.questID ) then
  859. self.Description.EditBox.Instructions:SetText(LFGListUtil_GetQuestDescription(activeEntryInfo.questID));
  860. else
  861. self.Description.EditBox.Instructions:SetText(DESCRIPTION_OF_YOUR_GROUP);
  862. end
  863. self.ItemLevel.EditBox:SetText(activeEntryInfo.requiredItemLevel ~= 0 and activeEntryInfo.requiredItemLevel or "");
  864. self.HonorLevel.EditBox:SetText(activeEntryInfo.requiredHonorLevel ~= 0 and activeEntryInfo.requiredHonorLevel or "")
  865. self.PrivateGroup.CheckButton:SetChecked(activeEntryInfo.privateGroup);
  866. self.ListGroupButton:SetText(DONE_EDITING);
  867. else
  868. UIDropDownMenu_EnableDropDown(self.CategoryDropDown);
  869. UIDropDownMenu_EnableDropDown(self.GroupDropDown);
  870. UIDropDownMenu_EnableDropDown(self.ActivityDropDown);
  871. self.ListGroupButton:SetText(LIST_GROUP);
  872. self.Name:Enable();
  873. self.Description.EditBox.Instructions:SetText(DESCRIPTION_OF_YOUR_GROUP);
  874. end
  875. end
  876. function LFGListEntryCreation_IsEditMode(self)
  877. return self.editMode;
  878. end
  879. function LFGListEntryCreationCancelButton_OnClick(self)
  880. local panel = self:GetParent();
  881. PlaySound(SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_ON);
  882. if ( LFGListEntryCreation_IsEditMode(panel) ) then
  883. LFGListFrame_SetActivePanel(panel:GetParent(), panel:GetParent().ApplicationViewer);
  884. else
  885. LFGListFrame_SetActivePanel(panel:GetParent(), panel:GetParent().CategorySelection);
  886. end
  887. end
  888. function LFGListEntryCreationListGroupButton_OnClick(self)
  889. PlaySound(SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_ON);
  890. LFGListEntryCreation_ListGroup(self:GetParent());
  891. end
  892. function LFGListEntryCreationActivityFinder_OnLoad(self)
  893. self.Dialog.ScrollFrame.update = function() LFGListEntryCreationActivityFinder_Update(self); end;
  894. self.Dialog.ScrollFrame.scrollBar.doNotHide = true;
  895. HybridScrollFrame_CreateButtons(self.Dialog.ScrollFrame, "LFGListEntryCreationActivityListTemplate");
  896. self.matchingActivities = {};
  897. end
  898. function LFGListEntryCreationActivityFinder_Show(self, categoryID, groupID, filters)
  899. self.Dialog.EntryBox:SetText("");
  900. self.categoryID = categoryID;
  901. self.groupID = groupID;
  902. self.filters = filters;
  903. self.selectedActivity = nil;
  904. LFGListEntryCreationActivityFinder_UpdateMatching(self);
  905. self:Show();
  906. self.Dialog.EntryBox:SetFocus();
  907. end
  908. function LFGListEntryCreationActivityFinder_UpdateMatching(self)
  909. local filters = ResolveCategoryFilters(self.categoryID, self.filters);
  910. self.matchingActivities = C_LFGList.GetAvailableActivities(self.categoryID, self.groupID, filters, self.Dialog.EntryBox:GetText());
  911. LFGListUtil_SortActivitiesByRelevancy(self.matchingActivities);
  912. if ( not self.selectedActivity or not tContains(self.matchingActivities, self.selectedActivity) ) then
  913. self.selectedActivity = self.matchingActivities[1];
  914. end
  915. LFGListEntryCreationActivityFinder_Update(self);
  916. end
  917. function LFGListEntryCreationActivityFinder_Update(self)
  918. local actitivities = self.matchingActivities;
  919. local offset = HybridScrollFrame_GetOffset(self.Dialog.ScrollFrame);
  920. for i=1, #self.Dialog.ScrollFrame.buttons do
  921. local button = self.Dialog.ScrollFrame.buttons[i];
  922. local idx = i + offset;
  923. local id = actitivities[idx];
  924. if ( id ) then
  925. button:SetText( (C_LFGList.GetActivityInfo(id)) );
  926. button.activityID = id;
  927. button.Selected:SetShown(self.selectedActivity == id);
  928. if ( self.selectedActivity == id ) then
  929. button:LockHighlight();
  930. else
  931. button:UnlockHighlight();
  932. end
  933. button:Show();
  934. else
  935. button:Hide();
  936. end
  937. end
  938. HybridScrollFrame_Update(self.Dialog.ScrollFrame, self.Dialog.ScrollFrame.buttons[1]:GetHeight() * #actitivities, self.Dialog.ScrollFrame:GetHeight());
  939. end
  940. function LFGListEntryCreationActivityFinder_Accept(self)
  941. if ( self.selectedActivity ) then
  942. LFGListEntryCreation_Select(self:GetParent(), nil, nil, nil, self.selectedActivity);
  943. end
  944. self:Hide();
  945. end
  946. function LFGListEntryCreationActivityFinder_Cancel(self)
  947. self:Hide();
  948. end
  949. function LFGListEntryCreationActivityFinder_Select(self, activityID)
  950. self.selectedActivity = activityID;
  951. LFGListEntryCreationActivityFinder_Update(self);
  952. end
  953. -------------------------------------------------------
  954. ----------Application Viewing
  955. -------------------------------------------------------
  956. function LFGListApplicationViewer_OnLoad(self)
  957. self.ScrollFrame.update = function() LFGListApplicationViewer_UpdateResults(self); end;
  958. self.ScrollFrame.dynamic = function(offset) return LFGListApplicationViewer_GetScrollOffset(self, offset) end
  959. self.ScrollFrame.scrollBar.doNotHide = true;
  960. self.NameColumnHeader:Disable();
  961. self.RoleColumnHeader:Disable();
  962. self.ItemLevelColumnHeader:Disable();
  963. HybridScrollFrame_CreateButtons(self.ScrollFrame, "LFGListApplicantTemplate");
  964. end
  965. function LFGListApplicationViewer_OnEvent(self, event, ...)
  966. if ( event == "LFG_LIST_ACTIVE_ENTRY_UPDATE" ) then
  967. LFGListApplicationViewer_UpdateInfo(self);
  968. elseif ( event == "PARTY_LEADER_CHANGED" ) then
  969. LFGListApplicationViewer_UpdateAvailability(self);
  970. LFGListApplicationViewer_UpdateInfo(self);
  971. elseif ( event == "LFG_LIST_APPLICANT_LIST_UPDATED" ) then
  972. LFGListApplicationViewer_UpdateResultList(self);
  973. LFGListApplicationViewer_UpdateResults(self);
  974. elseif ( event == "LFG_LIST_APPLICANT_UPDATED" ) then
  975. --If we can't make changes, we just remove people immediately
  976. local id = ...;
  977. if ( not LFGListUtil_IsEntryEmpowered() ) then
  978. C_LFGList.RemoveApplicant(id);
  979. end
  980. --Update whether we can invite people
  981. LFGListApplicationViewer_UpdateInviteState(self);
  982. elseif ( event == "GROUP_ROSTER_UPDATE" ) then
  983. LFGListApplicationViewer_UpdateAvailability(self);
  984. LFGListApplicationViewer_UpdateGroupData(self);
  985. LFGListApplicationViewer_UpdateInviteState(self);
  986. LFGListApplicationViewer_UpdateInfo(self);
  987. elseif ( event == "PLAYER_ROLES_ASSIGNED") then
  988. LFGListApplicationViewer_UpdateGroupData(self);
  989. end
  990. end
  991. function LFGListApplicationViewer_OnShow(self)
  992. C_LFGList.RefreshApplicants();
  993. LFGListApplicationViewer_UpdateResultList(self);
  994. LFGListApplicationViewer_UpdateResults(self);
  995. LFGListApplicationViewer_UpdateInfo(self);
  996. LFGListApplicationViewer_UpdateAvailability(self);
  997. LFGListApplicationViewer_UpdateGroupData(self);
  998. end
  999. function LFGListApplicationViewer_UpdateGroupData(self)
  1000. local activeEntryInfo = C_LFGList.GetActiveEntryInfo();
  1001. if ( not activeEntryInfo ) then
  1002. return;
  1003. end
  1004. local data = GetGroupMemberCountsForDisplay();
  1005. LFGListGroupDataDisplay_Update(self.DataDisplay, activeEntryInfo.activityID, data);
  1006. end
  1007. function LFGListApplicationViewer_UpdateInfo(self)
  1008. local activeEntryInfo = C_LFGList.GetActiveEntryInfo();
  1009. assert(activeEntryInfo);
  1010. local fullName, shortName, categoryID, groupID, iLevel, filters, minLevel, maxPlayers, displayType = C_LFGList.GetActivityInfo(activeEntryInfo.activityID);
  1011. local _, separateRecommended = C_LFGList.GetCategoryInfo(categoryID);
  1012. self.EntryName:SetWidth(0);
  1013. self.EntryName:SetText(activeEntryInfo.name);
  1014. self.DescriptionFrame.activityName = C_LFGList.GetActivityInfo(activeEntryInfo.activityID);
  1015. if ( activeEntryInfo.comment == "" and activeEntryInfo.questID ) then
  1016. activeEntryInfo.comment = LFGListUtil_GetQuestDescription(activeEntryInfo.questID);
  1017. end
  1018. self.DescriptionFrame.comment = activeEntryInfo.comment;
  1019. if ( activeEntryInfo.comment == "" ) then
  1020. self.DescriptionFrame.Text:SetText(self.DescriptionFrame.activityName);
  1021. else
  1022. self.DescriptionFrame.Text:SetFormattedText("%s |cff888888- %s|r", self.DescriptionFrame.activityName, self.DescriptionFrame.comment);
  1023. end
  1024. local hasRestrictions = false;
  1025. if ( activeEntryInfo.requiredItemLevel == 0 ) then
  1026. self.ItemLevel:SetText("");
  1027. else
  1028. self.ItemLevel:SetFormattedText(LFG_LIST_ITEM_LEVEL_CURRENT, activeEntryInfo.requiredItemLevel);
  1029. end
  1030. if ( activeEntryInfo.privateGroup ) then
  1031. self.PrivateGroup:SetText(LFG_LIST_PRIVATE);
  1032. self.ItemLevel:ClearAllPoints();
  1033. self.ItemLevel:SetPoint("LEFT", self.PrivateGroup, "RIGHT", 3, 0);
  1034. else
  1035. self.PrivateGroup:SetText("");
  1036. self.ItemLevel:ClearAllPoints();
  1037. self.ItemLevel:SetPoint("TOPLEFT", self.InfoBackground, "TOPLEFT", 12, -52);
  1038. end
  1039. if ( activeEntryInfo.voiceChat == "" ) then
  1040. self.VoiceChatFrame.tooltip = nil;
  1041. self.VoiceChatFrame:Hide();
  1042. else
  1043. self.VoiceChatFrame.tooltip = activeEntryInfo.voiceChat;
  1044. self.VoiceChatFrame:Show();
  1045. end
  1046. if ( self.EntryName:GetWidth() > 290 ) then
  1047. self.EntryName:SetWidth(290);
  1048. end
  1049. --Set the background
  1050. local atlasName = nil;
  1051. if ( separateRecommended and bit.band(filters, LE_LFG_LIST_FILTER_RECOMMENDED) ~= 0 ) then
  1052. atlasName = "groupfinder-background-"..(LFG_LIST_CATEGORY_TEXTURES[categoryID] or "raids").."-"..LFG_LIST_PER_EXPANSION_TEXTURES[LFGListUtil_GetCurrentExpansion()];
  1053. elseif ( separateRecommended and bit.band(filters, LE_LFG_LIST_FILTER_NOT_RECOMMENDED) ~= 0 ) then
  1054. atlasName = "groupfinder-background-"..(LFG_LIST_CATEGORY_TEXTURES[categoryID] or "raids").."-"..LFG_LIST_PER_EXPANSION_TEXTURES[math.max(0,LFGListUtil_GetCurrentExpansion() - 1)];
  1055. else
  1056. atlasName = "groupfinder-background-"..(LFG_LIST_CATEGORY_TEXTURES[categoryID] or "questing");
  1057. end
  1058. local suffix = "";
  1059. if ( bit.band(filters, LE_LFG_LIST_FILTER_PVE) ~= 0 ) then
  1060. suffix = "-pve";
  1061. elseif ( bit.band(filters, LE_LFG_LIST_FILTER_PVP) ~= 0 ) then
  1062. suffix = "-pvp";
  1063. end
  1064. --Try with the suffix and then without it
  1065. if ( not self.InfoBackground:SetAtlas(atlasName..suffix) ) then
  1066. self.InfoBackground:SetAtlas(atlasName);
  1067. end
  1068. --Update the AutoAccept button
  1069. self.AutoAcceptButton:SetChecked(activeEntryInfo.autoAccept);
  1070. if ( not C_LFGList.CanActiveEntryUseAutoAccept() ) then
  1071. self.AutoAcceptButton:Hide();
  1072. elseif ( UnitIsGroupLeader("player", LE_PARTY_CATEGORY_HOME) ) then
  1073. self.AutoAcceptButton:Show();
  1074. self.AutoAcceptButton:Enable();
  1075. self.AutoAcceptButton.Label:SetFontObject(GameFontHighlightSmall);
  1076. elseif ( UnitIsGroupAssistant("player", LE_PARTY_CATEGORY_HOME) ) then
  1077. self.AutoAcceptButton:Show();
  1078. self.AutoAcceptButton:Disable();
  1079. self.AutoAcceptButton.Label:SetFontObject(GameFontDisableSmall);
  1080. else
  1081. self.AutoAcceptButton:SetShown(activeEntryInfo.autoAccept);
  1082. self.AutoAcceptButton:Disable();
  1083. self.AutoAcceptButton.Label:SetFontObject(GameFontDisableSmall);
  1084. end
  1085. end
  1086. function LFGListApplicationViewer_UpdateAvailability(self)
  1087. if ( UnitIsGroupLeader("player", LE_PARTY_CATEGORY_HOME) ) then
  1088. self.RemoveEntryButton:Show();
  1089. self.EditButton:Show();
  1090. else
  1091. self.RemoveEntryButton:Hide();
  1092. self.EditButton:Hide();
  1093. end
  1094. if ( IsRestrictedAccount() ) then
  1095. self.EditButton:Disable();
  1096. self.EditButton.tooltip = ERR_RESTRICTED_ACCOUNT_LFG_LIST_TRIAL;
  1097. else
  1098. self.EditButton:Enable();
  1099. self.EditButton.tooltip = nil;
  1100. end
  1101. local empowered = LFGListUtil_IsEntryEmpowered();
  1102. self.UnempoweredCover:SetShown(not empowered);
  1103. self.ScrollFrame.NoApplicants:SetShown(empowered and (not self.applicants or #self.applicants == 0));
  1104. end
  1105. function LFGListApplicationViewer_UpdateResultList(self)
  1106. self.applicants = C_LFGList.GetApplicants();
  1107. --Sort applicants
  1108. LFGListUtil_SortApplicants(self.applicants);
  1109. --Cache off the group sizes for the scroll frame and the total height
  1110. local totalHeight = 0;
  1111. self.applicantSizes = {};
  1112. for i=1, #self.applicants do
  1113. local applicantInfo = C_LFGList.GetApplicantInfo(self.applicants[i]);
  1114. self.applicantSizes[i] = applicantInfo.numMembers;
  1115. totalHeight = totalHeight + LFGListApplicationViewerUtil_GetButtonHeight(applicantInfo.numMembers);
  1116. end
  1117. self.totalApplicantHeight = totalHeight;
  1118. LFGListApplicationViewer_UpdateAvailability(self);
  1119. end
  1120. function LFGListApplicationViewer_UpdateInviteState(self)
  1121. local activeEntryInfo = C_LFGList.GetActiveEntryInfo();
  1122. if ( not activeEntryInfo ) then
  1123. return;
  1124. end
  1125. local numAllowed = select(ACTIVITY_RETURN_VALUES.maxPlayers, C_LFGList.GetActivityInfo(activeEntryInfo.activityID, activeEntryInfo.questID));
  1126. if ( numAllowed == 0 ) then
  1127. numAllowed = MAX_RAID_MEMBERS;
  1128. end
  1129. local currentCount = GetNumGroupMembers(LE_PARTY_CATEGORY_HOME);
  1130. local numInvited = C_LFGList.GetNumInvitedApplicantMembers();
  1131. local buttons = self.ScrollFrame.buttons;
  1132. for i=1, #buttons do
  1133. local button = buttons[i];
  1134. if ( button.applicantID ) then
  1135. if ( button.numMembers + currentCount > numAllowed ) then
  1136. button.InviteButton:Disable();
  1137. button.InviteButton.tooltip = LFG_LIST_GROUP_TOO_FULL;
  1138. elseif ( button.numMembers + currentCount + numInvited > numAllowed ) then
  1139. button.InviteButton:Disable();
  1140. button.InviteButton.tooltip = LFG_LIST_INVITED_APP_FILLS_GROUP;
  1141. else
  1142. button.InviteButton:Enable();
  1143. button.InviteButton.tooltip = nil;
  1144. end
  1145. --If our mouse is already over the button, update the tooltip
  1146. if ( button.InviteButton:IsMouseOver() ) then
  1147. if ( button.InviteButton.tooltip ) then
  1148. button.InviteButton:GetScript("OnEnter")(button.InviteButton);
  1149. else
  1150. GameTooltip:Hide();
  1151. end
  1152. end
  1153. end
  1154. end
  1155. end
  1156. function LFGListApplicationViewer_UpdateResults(self)
  1157. local offset = HybridScrollFrame_GetOffset(self.ScrollFrame);
  1158. local buttons = self.ScrollFrame.buttons;
  1159. --If the mouse is over something in this frame, update it
  1160. local mouseover = GetMouseFocus();
  1161. local mouseoverParent = mouseover and mouseover:GetParent();
  1162. local parentParent = mouseoverParent and mouseoverParent:GetParent();
  1163. if ( mouseoverParent == self.ScrollFrame or parentParent == self.ScrollFrame ) then
  1164. --Just hide the tooltip. We should show it again inside the update function.
  1165. GameTooltip:Hide();
  1166. end
  1167. for i=1, #buttons do
  1168. local button = buttons[i];
  1169. local idx = i + offset;
  1170. local id = self.applicants[idx];
  1171. if ( id ) then
  1172. button.applicantID = id;
  1173. LFGListApplicationViewer_UpdateApplicant(button, id);
  1174. button.Background:SetAlpha(idx % 2 == 0 and 0.1 or 0.05);
  1175. button:Show();
  1176. else
  1177. button.applicantID = nil;
  1178. button:Hide();
  1179. end
  1180. end
  1181. HybridScrollFrame_Update(self.ScrollFrame, self.totalApplicantHeight, self.ScrollFrame:GetHeight());
  1182. LFGListApplicationViewer_UpdateInviteState(self);
  1183. end
  1184. function LFGListApplicationViewer_UpdateApplicant(button, id)
  1185. local applicantInfo = C_LFGList.GetApplicantInfo(id);
  1186. button:SetHeight(LFGListApplicationViewerUtil_GetButtonHeight(applicantInfo.numMembers));
  1187. --Update individual members
  1188. for i=1, applicantInfo.numMembers do
  1189. local member = button.Members[i];
  1190. if ( not member ) then
  1191. member = CreateFrame("BUTTON", nil, button, "LFGListApplicantMemberTemplate");
  1192. member:SetPoint("TOPLEFT", button.Members[i-1], "BOTTOMLEFT", 0, 0);
  1193. button.Members[i] = member;
  1194. end
  1195. LFGListApplicationViewer_UpdateApplicantMember(member, id, i, applicantInfo.applicationStatus, applicantInfo.pendingApplicationStatus);
  1196. member:Show();
  1197. end
  1198. --Hide extra member buttons
  1199. for i=applicantInfo.numMembers+1, #button.Members do
  1200. button.Members[i]:Hide();
  1201. end
  1202. --Update the Invite and Decline buttons based on group size
  1203. if ( applicantInfo.numMembers > 1 ) then
  1204. button.DeclineButton:SetHeight(36);
  1205. button.InviteButton:SetHeight(36);
  1206. button.InviteButton:SetFormattedText(LFG_LIST_INVITE_GROUP, applicantInfo.numMembers);
  1207. else
  1208. button.DeclineButton:SetHeight(22);
  1209. button.InviteButton:SetHeight(22);
  1210. button.InviteButton:SetText(INVITE);
  1211. end
  1212. if ( applicantInfo.applicantInfo or applicantInfo.applicationStatus == "applied" ) then
  1213. button.Status:Hide();
  1214. elseif ( applicantInfo.applicationStatus == "invited" ) then
  1215. button.Status:Show();
  1216. button.Status:SetText(LFG_LIST_APP_INVITED);
  1217. button.Status:SetTextColor(GREEN_FONT_COLOR.r, GREEN_FONT_COLOR.g, GREEN_FONT_COLOR.b);
  1218. elseif ( applicantInfo.applicationStatus == "failed" or applicantInfo.applicationStatus == "cancelled" ) then
  1219. button.Status:Show();
  1220. button.Status:SetText(LFG_LIST_APP_CANCELLED);
  1221. button.Status:SetTextColor(GRAY_FONT_COLOR.r, GRAY_FONT_COLOR.g, GRAY_FONT_COLOR.b);
  1222. elseif ( applicantInfo.applicationStatus == "declined" or applicantInfo.applicationStatus == "declined_full" or applicantInfo.applicationStatus == "declined_delisted" ) then
  1223. button.Status:Show();
  1224. button.Status:SetText(LFG_LIST_APP_DECLINED);
  1225. button.Status:SetTextColor(GRAY_FONT_COLOR.r, GRAY_FONT_COLOR.g, GRAY_FONT_COLOR.b);
  1226. elseif ( applicantInfo.applicationStatus == "timedout" ) then
  1227. button.Status:Show();
  1228. button.Status:SetText(LFG_LIST_APP_TIMED_OUT);
  1229. button.Status:SetTextColor(GRAY_FONT_COLOR.r, GRAY_FONT_COLOR.g, GRAY_FONT_COLOR.b);
  1230. elseif ( applicantInfo.applicationStatus == "inviteaccepted" ) then
  1231. button.Status:Show();
  1232. button.Status:SetText(LFG_LIST_APP_INVITE_ACCEPTED);
  1233. button.Status:SetTextColor(GREEN_FONT_COLOR.r, GREEN_FONT_COLOR.g, GREEN_FONT_COLOR.b);
  1234. elseif ( applicantInfo.applicationStatus == "invitedeclined" ) then
  1235. button.Status:Show();
  1236. button.Status:SetText(LFG_LIST_APP_INVITE_DECLINED);
  1237. button.Status:SetTextColor(GRAY_FONT_COLOR.r, GRAY_FONT_COLOR.g, GRAY_FONT_COLOR.b);
  1238. end
  1239. button.numMembers = applicantInfo.numMembers;
  1240. button.InviteButton:SetShown(not applicantInfo.applicantInfo and applicantInfo.applicationStatus == "applied" and LFGListUtil_IsEntryEmpowered());
  1241. button.DeclineButton:SetShown(not applicantInfo.applicantInfo and applicantInfo.applicationStatus ~= "invited" and LFGListUtil_IsEntryEmpowered());
  1242. button.DeclineButton.isAck = (applicantInfo.applicationStatus ~= "applied" and applicantInfo.applicationStatus ~= "invited");
  1243. button.Spinner:SetShown(applicantInfo.applicantInfo);
  1244. end
  1245. function LFGListApplicationViewer_UpdateRoleIcons(member, grayedOut, tank, healer, damage, noTouchy, assignedRole)
  1246. --Update the roles.
  1247. if ( grayedOut ) then
  1248. member.RoleIcon1:Hide();
  1249. member.RoleIcon2:Hide();
  1250. member.RoleIcon3:Hide();
  1251. else
  1252. local role1 = tank and "TANK" or (healer and "HEALER" or (damage and "DAMAGER"));
  1253. local role2 = (tank and healer and "HEALER") or ((tank or healer) and damage and "DAMAGER");
  1254. local role3 = (tank and healer and damage and "DAMAGER");
  1255. member.RoleIcon1:GetNormalTexture():SetAtlas(LFG_LIST_GROUP_DATA_ATLASES[role1]);
  1256. member.RoleIcon1:GetHighlightTexture():SetAtlas(LFG_LIST_GROUP_DATA_ATLASES[role1]);
  1257. if ( role2 ) then
  1258. member.RoleIcon2:GetNormalTexture():SetAtlas(LFG_LIST_GROUP_DATA_ATLASES[role2]);
  1259. member.RoleIcon2:GetHighlightTexture():SetAtlas(LFG_LIST_GROUP_DATA_ATLASES[role2]);
  1260. end
  1261. if ( role3 ) then
  1262. member.RoleIcon3:GetNormalTexture():SetAtlas(LFG_LIST_GROUP_DATA_ATLASES[role3]);
  1263. member.RoleIcon3:GetHighlightTexture():SetAtlas(LFG_LIST_GROUP_DATA_ATLASES[role3]);
  1264. end
  1265. member.RoleIcon1:SetEnabled(not noTouchy and role1 ~= assignedRole);
  1266. member.RoleIcon1:SetAlpha(role1 == assignedRole and 1 or 0.3);
  1267. member.RoleIcon1:Show();
  1268. member.RoleIcon2:SetEnabled(not noTouchy and role2 ~= assignedRole);
  1269. member.RoleIcon2:SetAlpha(role2 == assignedRole and 1 or 0.3);
  1270. member.RoleIcon2:SetShown(role2);
  1271. member.RoleIcon3:SetEnabled(not noTouchy and role3 ~= assignedRole);
  1272. member.RoleIcon3:SetAlpha(role3 == assignedRole and 1 or 0.3);
  1273. member.RoleIcon3:SetShown(role3);
  1274. member.RoleIcon1.role = role1;
  1275. member.RoleIcon2.role = role2;
  1276. member.RoleIcon3.role = role3;
  1277. end
  1278. end
  1279. function LFGListApplicationViewer_UpdateApplicantMember(member, appID, memberIdx, status, pendingStatus)
  1280. local grayedOut = not pendingStatus and (status == "failed" or status == "cancelled" or status == "declined" or status == "declined_full" or status == "declined_delisted" or status == "invitedeclined" or status == "timedout");
  1281. local noTouchy = (status == "invited" or status == "inviteaccepted" or status == "invitedeclined");
  1282. local name, class, localizedClass, level, itemLevel, honorLevel, tank, healer, damage, assignedRole, relationship = C_LFGList.GetApplicantMemberInfo(appID, memberIdx);
  1283. member.memberIdx = memberIdx;
  1284. member.Name:SetWidth(0);
  1285. if ( name ) then
  1286. local displayName = Ambiguate(name, "short");
  1287. if ( memberIdx > 1 ) then
  1288. member.Name:SetText(" "..displayName);
  1289. else
  1290. member.Name:SetText(displayName);
  1291. end
  1292. local classTextColor = grayedOut and GRAY_FONT_COLOR or RAID_CLASS_COLORS[class];
  1293. member.Name:SetTextColor(classTextColor.r, classTextColor.g, classTextColor.b);
  1294. else
  1295. --We might still be requesting the name and class from the server.
  1296. member.Name:SetText("");
  1297. end
  1298. member.FriendIcon:SetShown(relationship);
  1299. member.FriendIcon.relationship = relationship;
  1300. member.FriendIcon.Icon:SetDesaturated(grayedOut);
  1301. member.FriendIcon:SetAlpha(grayedOut and 0.5 or 1.0);
  1302. --Adjust name width depending on whether we have the friend icon
  1303. local nameLength = 100;
  1304. if ( relationship ) then
  1305. nameLength = nameLength - 22;
  1306. end
  1307. if ( member.Name:GetWidth() > nameLength ) then
  1308. member.Name:SetWidth(nameLength);
  1309. end
  1310. LFGListApplicationViewer_UpdateRoleIcons(member, grayedOut, tank, healer, damage, noTouchy, assignedRole);
  1311. member.ItemLevel:SetShown(not grayedOut);
  1312. member.ItemLevel:SetText(math.floor(itemLevel));
  1313. local mouseFocus = GetMouseFocus();
  1314. if ( mouseFocus == member ) then
  1315. LFGListApplicantMember_OnEnter(member);
  1316. elseif ( mouseFocus == member.FriendIcon ) then
  1317. member.FriendIcon:GetScript("OnEnter")(member.FriendIcon);
  1318. end
  1319. end
  1320. function LFGListApplicationViewer_GetScrollOffset(self, offset)
  1321. local acum = 0;
  1322. for i=1, #self.applicantSizes do
  1323. local height = LFGListApplicationViewerUtil_GetButtonHeight(self.applicantSizes[i]);
  1324. acum = acum + height;
  1325. if ( acum > offset ) then
  1326. return i - 1, height + offset - acum;
  1327. end
  1328. end
  1329. --We're scrolled completely off the bottom
  1330. return #self.applicantSizes, 0;
  1331. end
  1332. function LFGListApplicationViewerUtil_GetButtonHeight(numApplicants)
  1333. return 20 * numApplicants + 6;
  1334. end
  1335. function LFGListApplicationViewerEditButton_OnClick(self)
  1336. PlaySound(SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_ON);
  1337. local panel = self:GetParent();
  1338. local entryCreation = panel:GetParent().EntryCreation;
  1339. LFGListEntryCreation_SetEditMode(entryCreation, true);
  1340. LFGListFrame_SetActivePanel(panel:GetParent(), entryCreation);
  1341. end
  1342. --Applicant members
  1343. function LFGListApplicantMember_OnEnter(self)
  1344. local applicantID = self:GetParent().applicantID;
  1345. local memberIdx = self.memberIdx;
  1346. local activeEntryInfo = C_LFGList.GetActiveEntryInfo();
  1347. if ( not activeEntryInfo ) then
  1348. return;
  1349. end
  1350. local useHonorLevel = select(11, C_LFGList.GetActivityInfo(activeEntryInfo.activityID));
  1351. local applicantInfo = C_LFGList.GetApplicantInfo(applicantID);
  1352. local name, class, localizedClass, level, itemLevel, honorLevel, tank, healer, damage, assignedRole = C_LFGList.GetApplicantMemberInfo(applicantID, memberIdx);
  1353. GameTooltip:SetOwner(self, "ANCHOR_NONE");
  1354. GameTooltip:SetPoint("BOTTOMLEFT", self, "TOPLEFT", 105, 0);
  1355. if ( name ) then
  1356. local classTextColor = RAID_CLASS_COLORS[class];
  1357. GameTooltip:SetText(name, classTextColor.r, classTextColor.g, classTextColor.b);
  1358. GameTooltip:AddLine(string.format(UNIT_TYPE_LEVEL_TEMPLATE, level, localizedClass), 1, 1, 1);
  1359. else
  1360. GameTooltip:SetText(" "); --Just make it empty until we get the name update
  1361. end
  1362. GameTooltip:AddLine(string.format(LFG_LIST_ITEM_LEVEL_CURRENT, itemLevel), 1, 1, 1);
  1363. if ( useHonorLevel ) then
  1364. GameTooltip:AddLine(string.format(LFG_LIST_HONOR_LEVEL_CURRENT_PVP, honorLevel), 1, 1, 1);
  1365. end
  1366. if ( applicantInfo.comment and applicantInfo.comment ~= "" ) then
  1367. GameTooltip:AddLine(" ");
  1368. GameTooltip:AddLine(string.format(LFG_LIST_COMMENT_FORMAT, applicantInfo.comment), LFG_LIST_COMMENT_FONT_COLOR.r, LFG_LIST_COMMENT_FONT_COLOR.g, LFG_LIST_COMMENT_FONT_COLOR.b, true);
  1369. end
  1370. --Add statistics
  1371. local stats = C_LFGList.GetApplicantMemberStats(applicantID, memberIdx);
  1372. local lastTitle = nil;
  1373. --Tank proving ground
  1374. if ( stats[23690] and stats[23690] > 0 ) then
  1375. LFGListUtil_AppendStatistic(LFG_LIST_PROVING_TANK_GOLD, nil, LFG_LIST_PROVING_GROUND_TITLE, lastTitle);
  1376. lastTitle = LFG_LIST_PROVING_GROUND_TITLE;
  1377. elseif ( stats[23687] and stats[23687] > 0 ) then
  1378. LFGListUtil_AppendStatistic(LFG_LIST_PROVING_TANK_SILVER, nil, LFG_LIST_PROVING_GROUND_TITLE, lastTitle);
  1379. lastTitle = LFG_LIST_PROVING_GROUND_TITLE;
  1380. elseif ( stats[23684] and stats[23684] > 0 ) then
  1381. LFGListUtil_AppendStatistic(LFG_LIST_PROVING_TANK_BRONZE, nil, LFG_LIST_PROVING_GROUND_TITLE, lastTitle);
  1382. lastTitle = LFG_LIST_PROVING_GROUND_TITLE;
  1383. end
  1384. --Healer proving ground
  1385. if ( stats[23691] and stats[23691] > 0 ) then
  1386. LFGListUtil_AppendStatistic(LFG_LIST_PROVING_HEALER_GOLD, nil, LFG_LIST_PROVING_GROUND_TITLE, lastTitle);
  1387. lastTitle = LFG_LIST_PROVING_GROUND_TITLE;
  1388. elseif ( stats[23688] and stats[23688] > 0 ) then
  1389. LFGListUtil_AppendStatistic(LFG_LIST_PROVING_HEALER_SILVER, nil, LFG_LIST_PROVING_GROUND_TITLE, lastTitle);
  1390. lastTitle = LFG_LIST_PROVING_GROUND_TITLE;
  1391. elseif ( stats[23685] and stats[23685] > 0 ) then
  1392. LFGListUtil_AppendStatistic(LFG_LIST_PROVING_HEALER_BRONZE, nil, LFG_LIST_PROVING_GROUND_TITLE, lastTitle);
  1393. lastTitle = LFG_LIST_PROVING_GROUND_TITLE;
  1394. end
  1395. --Damage proving ground
  1396. if ( stats[23689] and stats[23689] > 0 ) then
  1397. LFGListUtil_AppendStatistic(LFG_LIST_PROVING_DAMAGER_GOLD, nil, LFG_LIST_PROVING_GROUND_TITLE, lastTitle);
  1398. lastTitle = LFG_LIST_PROVING_GROUND_TITLE;
  1399. elseif ( stats[23686] and stats[23686] > 0 ) then
  1400. LFGListUtil_AppendStatistic(LFG_LIST_PROVING_DAMAGER_SILVER, nil, LFG_LIST_PROVING_GROUND_TITLE, lastTitle);
  1401. lastTitle = LFG_LIST_PROVING_GROUND_TITLE;
  1402. elseif ( stats[23683] and stats[23683] > 0 ) then
  1403. LFGListUtil_AppendStatistic(LFG_LIST_PROVING_DAMAGER_BRONZE, nil, LFG_LIST_PROVING_GROUND_TITLE, lastTitle);
  1404. lastTitle = LFG_LIST_PROVING_GROUND_TITLE;
  1405. end
  1406. GameTooltip:Show();
  1407. end
  1408. -------------------------------------------------------
  1409. ----------Searching
  1410. -------------------------------------------------------
  1411. function LFGListSearchPanel_OnLoad(self)
  1412. self.SearchBox.Instructions:SetText(FILTER);
  1413. self.ScrollFrame.update = function() LFGListSearchPanel_UpdateResults(self); end;
  1414. self.ScrollFrame.scrollBar.doNotHide = true;
  1415. HybridScrollFrame_CreateButtons(self.ScrollFrame, "LFGListSearchEntryTemplate");
  1416. self.SearchBox.clearButton:SetScript("OnClick", function(btn)
  1417. PlaySound(SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_ON);
  1418. local editBox = btn:GetParent();
  1419. C_LFGList.ClearSearchTextFields();
  1420. editBox:ClearFocus();
  1421. LFGListSearchPanel_DoSearch(self);
  1422. end);
  1423. end
  1424. function LFGListSearchPanel_OnEvent(self, event, ...)
  1425. --Note: events are dispatched from the base frame. Add RegisterEvent there.
  1426. if ( event == "LFG_LIST_SEARCH_RESULTS_RECEIVED" ) then
  1427. StaticPopupSpecial_Hide(LFGListApplicationDialog);
  1428. if ( self.searching ) then
  1429. -- got new list from server, everything we were filtering out should be gone
  1430. self.filteredIDs = nil;
  1431. end
  1432. self.searching = false;
  1433. self.searchFailed = false;
  1434. LFGListSearchPanel_UpdateResultList(self);
  1435. LFGListSearchPanel_UpdateResults(self);
  1436. elseif ( event == "LFG_LIST_SEARCH_FAILED" ) then
  1437. self.searching = false;
  1438. self.searchFailed = true;
  1439. LFGListSearchPanel_UpdateResultList(self);
  1440. LFGListSearchPanel_UpdateResults(self);
  1441. elseif ( event == "LFG_LIST_SEARCH_RESULT_UPDATED" ) then
  1442. local id = ...;
  1443. if ( self.selectedResult == id ) then
  1444. LFGListSearchPanel_ValidateSelected(self);
  1445. if ( self.selectedResult ~= id ) then
  1446. LFGListSearchPanel_UpdateResults(self);
  1447. end
  1448. end
  1449. LFGListSearchPanel_UpdateButtonStatus(self);
  1450. elseif ( event == "PARTY_LEADER_CHANGED" ) then
  1451. LFGListSearchPanel_UpdateButtonStatus(self);
  1452. elseif ( event == "GROUP_ROSTER_UPDATE" ) then
  1453. LFGListSearchPanel_UpdateButtonStatus(self);
  1454. elseif ( event == "PLAYER_SPECIALIZATION_CHANGED" ) then
  1455. local unit = ...;
  1456. if ( unit == "player" ) then
  1457. LFGListSearchPanel_UpdateButtonStatus(self);
  1458. end
  1459. elseif ( event == "UNIT_CONNECTION" ) then
  1460. LFGListSearchPanel_UpdateButtonStatus(self);
  1461. end
  1462. if ( tContains(LFG_LIST_ACTIVE_QUEUE_MESSAGE_EVENTS, event) ) then
  1463. LFGListSearchPanel_UpdateButtonStatus(self);
  1464. end
  1465. end
  1466. function LFGListSearchPanel_AddFilteredID(self, id)
  1467. if ( not self.filteredIDs ) then
  1468. self.filteredIDs = { };
  1469. end
  1470. tinsert(self.filteredIDs, id);
  1471. end
  1472. function LFGListSearchPanel_OnShow(self)
  1473. LFGListSearchPanel_UpdateResultList(self);
  1474. LFGListSearchPanel_UpdateResults(self);
  1475. --LFGListSearchPanel_UpdateButtonStatus(self); --Called by UpdateResults
  1476. local availableLanguages = C_LFGList.GetAvailableLanguageSearchFilter();
  1477. local defaultLanguages = C_LFGList.GetDefaultLanguageSearchFilter();
  1478. local canChangeLanguages = false;
  1479. for i=1, #availableLanguages do
  1480. if ( not defaultLanguages[availableLanguages[i]] ) then
  1481. canChangeLanguages = true;
  1482. break;
  1483. end
  1484. end
  1485. if ( canChangeLanguages ) then
  1486. self.SearchBox:SetWidth(228);
  1487. self.FilterButton:Show();
  1488. else
  1489. self.SearchBox:SetWidth(319);
  1490. self.FilterButton:Hide();
  1491. end
  1492. end
  1493. function LFGListSearchPanel_Clear(self)
  1494. C_LFGList.ClearSearchResults();
  1495. C_LFGList.ClearSearchTextFields();
  1496. self.selectedResult = nil;
  1497. LFGListSearchPanel_UpdateResultList(self);
  1498. LFGListSearchPanel_UpdateResults(self);
  1499. end
  1500. function LFGListSearchPanel_SetCategory(self, categoryID, filters, preferredFilters)
  1501. self.categoryID = categoryID;
  1502. self.filters = filters;
  1503. self.preferredFilters = preferredFilters;
  1504. local name = LFGListUtil_GetDecoratedCategoryName(C_LFGList.GetCategoryInfo(categoryID), filters, false);
  1505. self.CategoryName:SetText(name);
  1506. end
  1507. function LFGListSearchPanel_DoSearch(self)
  1508. local searchText = self.SearchBox:GetText();
  1509. local languages = C_LFGList.GetLanguageSearchFilter();
  1510. local filters = ResolveCategoryFilters(self.categoryID, self.filters);
  1511. C_LFGList.Search(self.categoryID, filters, self.preferredFilters, languages);
  1512. self.searching = true;
  1513. self.searchFailed = false;
  1514. self.selectedResult = nil;
  1515. LFGListSearchPanel_UpdateResultList(self);
  1516. LFGListSearchPanel_UpdateResults(self);
  1517. -- If auto-create is desired, then the caller needs to set up that data after the search begins.
  1518. -- There's an issue with using OnTextChanged to handle this due to how OnShow processes the update.
  1519. if self.previousSearchText ~= searchText then
  1520. LFGListEntryCreation_ClearAutoCreateMode(self:GetParent().EntryCreation);
  1521. end
  1522. self.previousSearchText = searchText;
  1523. end
  1524. function LFGListSearchPanel_CreateGroupInstead(self)
  1525. PlaySound(SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_ON);
  1526. local panel = self:GetParent():GetParent();
  1527. LFGListEntryCreation_Show(panel:GetParent().EntryCreation, panel.preferredFilters, panel.categoryID, panel.filters);
  1528. end
  1529. function LFGListSearchPanel_UpdateResultList(self)
  1530. self.totalResults, self.results = C_LFGList.GetSearchResults();
  1531. self.applications = C_LFGList.GetApplications();
  1532. if ( self.filteredIDs ) then
  1533. LFGListUtil_FilterSearchResults(self.results, self.filteredIDs);
  1534. end
  1535. LFGListUtil_SortSearchResults(self.results);
  1536. end
  1537. function LFGListSearchPanel_ValidateSelected(self)
  1538. if ( self.selectedResult and not LFGListSearchPanelUtil_CanSelectResult(self.selectedResult)) then
  1539. self.selectedResult = nil;
  1540. end
  1541. end
  1542. function LFGListSearchPanelUtil_CanSelectResult(resultID)
  1543. local _, appStatus, pendingStatus, appDuration = C_LFGList.GetApplicationInfo(resultID);
  1544. local searchResultInfo = C_LFGList.GetSearchResultInfo(resultID);
  1545. if ( appStatus ~= "none" or pendingStatus or searchResultInfo.isDelisted ) then
  1546. return false;
  1547. end
  1548. return true;
  1549. end
  1550. function LFGListSearchPanel_UpdateResults(self)
  1551. local offset = HybridScrollFrame_GetOffset(self.ScrollFrame);
  1552. local buttons = self.ScrollFrame.buttons;
  1553. --If we have an application selected, deselect it.
  1554. LFGListSearchPanel_ValidateSelected(self);
  1555. if ( self.searching ) then
  1556. self.SearchingSpinner:Show();
  1557. self.ScrollFrame.NoResultsFound:Hide();
  1558. self.ScrollFrame.StartGroupButton:Hide();
  1559. for i=1, #buttons do
  1560. buttons[i]:Hide();
  1561. end
  1562. else
  1563. self.SearchingSpinner:Hide();
  1564. local results = self.results;
  1565. local apps = self.applications;
  1566. for i=1, #buttons do
  1567. local button = buttons[i];
  1568. local idx = i + offset;
  1569. local result = (idx <= #apps) and apps[idx] or results[idx - #apps];
  1570. if ( result ) then
  1571. button.resultID = result;
  1572. LFGListSearchEntry_Update(button);
  1573. button:Show();
  1574. else
  1575. button.resultID = nil;
  1576. button:Hide();
  1577. end
  1578. end
  1579. local totalHeight = buttons[1]:GetHeight() * (#results + #apps);
  1580. --Reanchor the errors to not overlap applications
  1581. if ( totalHeight < self.ScrollFrame:GetHeight() ) then
  1582. self.ScrollFrame.NoResultsFound:SetPoint("TOP", self.ScrollFrame, "TOP", 0, -totalHeight - 27);
  1583. end
  1584. if(self.totalResults == 0) then
  1585. self.ScrollFrame.NoResultsFound:Show();
  1586. self.ScrollFrame.StartGroupButton:SetShown(not self.searchFailed);
  1587. self.ScrollFrame.StartGroupButton:ClearAllPoints();
  1588. self.ScrollFrame.StartGroupButton:SetPoint("BOTTOM", self.ScrollFrame.NoResultsFound, "BOTTOM", 0, - 27);
  1589. self.ScrollFrame.NoResultsFound:SetText(self.searchFailed and LFG_LIST_SEARCH_FAILED or LFG_LIST_NO_RESULTS_FOUND);
  1590. elseif(self.shouldAlwaysShowCreateGroupButton) then
  1591. self.ScrollFrame.NoResultsFound:Hide();
  1592. self.ScrollFrame.StartGroupButton:SetShown(not self.searchFailed);
  1593. self.ScrollFrame.StartGroupButton:ClearAllPoints();
  1594. self.ScrollFrame.StartGroupButton:SetPoint("TOP", self.ScrollFrame, "TOP", 0, -totalHeight - 15);
  1595. else
  1596. self.ScrollFrame.NoResultsFound:Hide();
  1597. end
  1598. HybridScrollFrame_Update(self.ScrollFrame, totalHeight, self.ScrollFrame:GetHeight());
  1599. end
  1600. LFGListSearchPanel_UpdateButtonStatus(self);
  1601. end
  1602. function LFGListSearchPanel_SelectResult(self, resultID)
  1603. self.selectedResult = resultID;
  1604. LFGListSearchPanel_UpdateResults(self);
  1605. end
  1606. function LFGListSearchPanel_UpdateButtonStatus(self)
  1607. --Update the SignUpButton
  1608. local resultID = self.selectedResult;
  1609. local numApplications, numActiveApplications = C_LFGList.GetNumApplications();
  1610. local messageApply = LFGListUtil_GetActiveQueueMessage(true);
  1611. local availTank, availHealer, availDPS = C_LFGList.GetAvailableRoles();
  1612. if ( messageApply ) then
  1613. self.SignUpButton:Disable();
  1614. self.SignUpButton.tooltip = messageApply;
  1615. elseif ( not LFGListUtil_IsAppEmpowered() ) then
  1616. self.SignUpButton:Disable();
  1617. self.SignUpButton.tooltip = LFG_LIST_APP_UNEMPOWERED;
  1618. elseif ( IsInGroup(LE_PARTY_CATEGORY_HOME) and C_LFGList.IsCurrentlyApplying() ) then
  1619. self.SignUpButton:Disable();
  1620. self.SignUpButton.tooltip = LFG_LIST_APP_CURRENTLY_APPLYING;
  1621. elseif ( numActiveApplications >= MAX_LFG_LIST_APPLICATIONS ) then
  1622. self.SignUpButton:Disable();
  1623. self.SignUpButton.tooltip = string.format(LFG_LIST_HIT_MAX_APPLICATIONS, MAX_LFG_LIST_APPLICATIONS);
  1624. elseif ( GetNumGroupMembers(LE_PARTY_CATEGORY_HOME) > MAX_PARTY_MEMBERS + 1 ) then
  1625. self.SignUpButton:Disable();
  1626. self.SignUpButton.tooltip = LFG_LIST_MAX_MEMBERS;
  1627. elseif ( not (availTank or availHealer or availDPS) ) then
  1628. self.SignUpButton:Disable();
  1629. self.SignUpButton.tooltip = LFG_LIST_MUST_CHOOSE_SPEC;
  1630. elseif ( GroupHasOfflineMember(LE_PARTY_CATEGORY_HOME) ) then
  1631. self.SignUpButton:Disable();
  1632. self.SignUpButton.tooltip = LFG_LIST_OFFLINE_MEMBER;
  1633. elseif ( resultID ) then
  1634. self.SignUpButton:Enable();
  1635. self.SignUpButton.tooltip = nil;
  1636. else
  1637. self.SignUpButton:Disable();
  1638. self.SignUpButton.tooltip = LFG_LIST_SELECT_A_SEARCH_RESULT;
  1639. end
  1640. --Update the StartGroupButton
  1641. if ( IsInGroup(LE_PARTY_CATEGORY_HOME) and not UnitIsGroupLeader("player", LE_PARTY_CATEGORY_HOME) ) then
  1642. self.ScrollFrame.StartGroupButton:Disable();
  1643. self.ScrollFrame.StartGroupButton.tooltip = LFG_LIST_NOT_LEADER;
  1644. else
  1645. local messageStart = LFGListUtil_GetActiveQueueMessage(false);
  1646. local startError, errorText = GetStartGroupRestriction();
  1647. if ( messageStart ) then
  1648. self.ScrollFrame.StartGroupButton:Disable();
  1649. self.ScrollFrame.StartGroupButton.tooltip = messageStart;
  1650. elseif ( startError ~= nil ) then
  1651. self.ScrollFrame.StartGroupButton:Disable();
  1652. self.ScrollFrame.StartGroupButton.tooltip = errorText;
  1653. else
  1654. self.ScrollFrame.StartGroupButton:Enable();
  1655. self.ScrollFrame.StartGroupButton.tooltip = nil;
  1656. end
  1657. end
  1658. end
  1659. function LFGListSearchPanel_SignUp(self)
  1660. LFGListApplicationDialog_Show(LFGListApplicationDialog, self.selectedResult);
  1661. end
  1662. function LFGListSearchPanelSearchBox_OnEnterPressed(self)
  1663. local parent = self:GetParent();
  1664. if ( parent.AutoCompleteFrame:IsShown() and parent.AutoCompleteFrame.selected ) then
  1665. C_LFGList.SetSearchToActivity(parent.AutoCompleteFrame.selected);
  1666. end
  1667. LFGListSearchPanel_DoSearch(self:GetParent());
  1668. self:ClearFocus();
  1669. end
  1670. function LFGListSearchPanelSearchBox_OnTabPressed(self)
  1671. if ( IsShiftKeyDown() ) then
  1672. LFGListSearchPanel_AutoCompleteAdvance(self:GetParent(), -1);
  1673. else
  1674. LFGListSearchPanel_AutoCompleteAdvance(self:GetParent(), 1);
  1675. end
  1676. end
  1677. function LFGListSearchPanelSearchBox_OnArrowPressed(self, key)
  1678. if ( key == "UP" ) then
  1679. LFGListSearchPanel_AutoCompleteAdvance(self:GetParent(), -1);
  1680. elseif ( key == "DOWN" ) then
  1681. LFGListSearchPanel_AutoCompleteAdvance(self:GetParent(), 1);
  1682. end
  1683. end
  1684. function LFGListSearchPanelSearchBox_OnTextChanged(self)
  1685. SearchBoxTemplate_OnTextChanged(self);
  1686. LFGListSearchPanel_UpdateAutoComplete(self:GetParent());
  1687. end
  1688. function LFGListSearchAutoCompleteButton_OnClick(self)
  1689. local panel = self:GetParent():GetParent();
  1690. PlaySound(SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_ON);
  1691. C_LFGList.SetSearchToActivity(self.activityID);
  1692. LFGListSearchPanel_DoSearch(panel);
  1693. panel.SearchBox:ClearFocus();
  1694. end
  1695. function LFGListSearchPanel_AutoCompleteAdvance(self, offset)
  1696. local selected = self.AutoCompleteFrame.selected;
  1697. --Find the index of the current selection and how many results we have displayed
  1698. local idx = nil;
  1699. local numDisplayed = 0;
  1700. for i=1, #self.AutoCompleteFrame.Results do
  1701. local btn = self.AutoCompleteFrame.Results[i];
  1702. if ( btn:IsShown() and btn.activityID ) then
  1703. numDisplayed = i;
  1704. if ( btn.activityID == selected ) then
  1705. idx = i;
  1706. end
  1707. else
  1708. break;
  1709. end
  1710. end
  1711. local newIndex = nil;
  1712. if ( not idx ) then
  1713. --We had nothing selected, advance from the front or back
  1714. if ( offset > 0 ) then
  1715. newIndex = offset;
  1716. else
  1717. newIndex = numDisplayed + 1 + offset;
  1718. end
  1719. else
  1720. --Advance from our old location
  1721. newIndex = ((idx - 1 + offset + numDisplayed) % numDisplayed) + 1;
  1722. end
  1723. self.AutoCompleteFrame.selected = self.AutoCompleteFrame.Results[newIndex].activityID;
  1724. LFGListSearchPanel_UpdateAutoComplete(self);
  1725. end
  1726. function LFGListSearchPanel_UpdateAutoComplete(self)
  1727. local text = self.SearchBox:GetText();
  1728. if ( text == "" or not self.SearchBox:HasFocus() ) then
  1729. self.AutoCompleteFrame:Hide();
  1730. self.AutoCompleteFrame.selected = nil;
  1731. return;
  1732. end
  1733. --Choose the autocomplete results
  1734. local filters = ResolveCategoryFilters(self.categoryID, self.filters);
  1735. local matchingActivities = C_LFGList.GetAvailableActivities(self.categoryID, nil, filters, text);
  1736. LFGListUtil_SortActivitiesByRelevancy(matchingActivities);
  1737. local numResults = math.min(#matchingActivities, MAX_LFG_LIST_SEARCH_AUTOCOMPLETE_ENTRIES);
  1738. if ( numResults == 0 ) then
  1739. self.AutoCompleteFrame:Hide();
  1740. self.AutoCompleteFrame.selected = nil;
  1741. return;
  1742. end
  1743. --Update the buttons
  1744. local foundSelected = false;
  1745. for i=1, numResults do
  1746. local id = matchingActivities[i];
  1747. local button = self.AutoCompleteFrame.Results[i];
  1748. if ( not button ) then
  1749. button = CreateFrame("BUTTON", nil, self.AutoCompleteFrame, "LFGListSearchAutoCompleteButtonTemplate");
  1750. button:SetPoint("TOPLEFT", self.AutoCompleteFrame.Results[i-1], "BOTTOMLEFT", 0, 0);
  1751. button:SetPoint("TOPRIGHT", self.AutoCompleteFrame.Results[i-1], "BOTTOMRIGHT", 0, 0);
  1752. self.AutoCompleteFrame.Results[i] = button;
  1753. end
  1754. if ( i == numResults and numResults < #matchingActivities ) then
  1755. --This is just a "x more" button
  1756. button:SetFormattedText(LFG_LIST_AND_MORE, #matchingActivities - numResults + 1);
  1757. button:Disable();
  1758. button.Selected:Hide();
  1759. button.activityID = nil;
  1760. else
  1761. --This is an actual activity
  1762. button:SetText( (C_LFGList.GetActivityInfo(id)) );
  1763. button:Enable();
  1764. button.activityID = id;
  1765. if ( id == self.AutoCompleteFrame.selected ) then
  1766. button.Selected:Show();
  1767. foundSelected = true;
  1768. else
  1769. button.Selected:Hide();
  1770. end
  1771. end
  1772. button:Show();
  1773. end
  1774. if ( not foundSelected ) then
  1775. self.selected = nil;
  1776. end
  1777. --Hide unused buttons
  1778. for i=numResults + 1, #self.AutoCompleteFrame.Results do
  1779. self.AutoCompleteFrame.Results[i]:Hide();
  1780. end
  1781. --Update the frames height and show it
  1782. self.AutoCompleteFrame:SetHeight(numResults * self.AutoCompleteFrame.Results[1]:GetHeight() + 8);
  1783. self.AutoCompleteFrame:Show();
  1784. end
  1785. function LFGListSearchEntry_OnLoad(self)
  1786. self:RegisterEvent("LFG_LIST_SEARCH_RESULT_UPDATED");
  1787. self:RegisterEvent("LFG_ROLE_CHECK_UPDATE");
  1788. self:RegisterForClicks("LeftButtonUp", "RightButtonUp");
  1789. end
  1790. function LFGListSearchEntry_Update(self)
  1791. local resultID = self.resultID;
  1792. local _, appStatus, pendingStatus, appDuration = C_LFGList.GetApplicationInfo(resultID);
  1793. local isApplication = (appStatus ~= "none" or pendingStatus);
  1794. local isAppFinished = LFGListUtil_IsStatusInactive(appStatus) or LFGListUtil_IsStatusInactive(pendingStatus);
  1795. --Update visibility based on whether we're an application or not
  1796. self.isApplication = isApplication;
  1797. self.ApplicationBG:SetShown(isApplication and not isAppFinished);
  1798. self.ResultBG:SetShown(not isApplication or isAppFinished);
  1799. self.DataDisplay:SetShown(not isApplication);
  1800. self.CancelButton:SetShown(isApplication and pendingStatus ~= "applied");
  1801. self.CancelButton:SetEnabled(LFGListUtil_IsAppEmpowered());
  1802. self.CancelButton.Icon:SetDesaturated(not LFGListUtil_IsAppEmpowered());
  1803. self.CancelButton.tooltip = (not LFGListUtil_IsAppEmpowered()) and LFG_LIST_APP_UNEMPOWERED;
  1804. self.Spinner:SetShown(pendingStatus == "applied");
  1805. if ( pendingStatus == "applied" and C_LFGList.GetRoleCheckInfo() ) then
  1806. self.PendingLabel:SetText(LFG_LIST_ROLE_CHECK);
  1807. self.PendingLabel:SetTextColor(NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b);
  1808. self.PendingLabel:Show();
  1809. self.ExpirationTime:Hide();
  1810. self.CancelButton:Hide();
  1811. elseif ( pendingStatus == "cancelled" or appStatus == "cancelled" or appStatus == "failed" ) then
  1812. self.PendingLabel:SetText(LFG_LIST_APP_CANCELLED);
  1813. self.PendingLabel:SetTextColor(RED_FONT_COLOR.r, RED_FONT_COLOR.g, RED_FONT_COLOR.b);
  1814. self.PendingLabel:Show();
  1815. self.ExpirationTime:Hide();
  1816. self.CancelButton:Hide();
  1817. elseif ( appStatus == "declined" or appStatus == "declined_full" or appStatus == "declined_delisted" ) then
  1818. self.PendingLabel:SetText(LFG_LIST_APP_DECLINED);
  1819. self.PendingLabel:SetTextColor(RED_FONT_COLOR.r, RED_FONT_COLOR.g, RED_FONT_COLOR.b);
  1820. self.PendingLabel:Show();
  1821. self.ExpirationTime:Hide();
  1822. self.CancelButton:Hide();
  1823. elseif ( appStatus == "timedout" ) then
  1824. self.PendingLabel:SetText(LFG_LIST_APP_TIMED_OUT);
  1825. self.PendingLabel:SetTextColor(RED_FONT_COLOR.r, RED_FONT_COLOR.g, RED_FONT_COLOR.b);
  1826. self.PendingLabel:Show();
  1827. self.ExpirationTime:Hide();
  1828. self.CancelButton:Hide();
  1829. elseif ( appStatus == "invited" ) then
  1830. self.PendingLabel:SetText(LFG_LIST_APP_INVITED);
  1831. self.PendingLabel:SetTextColor(GREEN_FONT_COLOR.r, GREEN_FONT_COLOR.g, GREEN_FONT_COLOR.b);
  1832. self.PendingLabel:Show();
  1833. self.ExpirationTime:Hide();
  1834. self.CancelButton:Hide();
  1835. elseif ( appStatus == "inviteaccepted" ) then
  1836. self.PendingLabel:SetText(LFG_LIST_APP_INVITE_ACCEPTED);
  1837. self.PendingLabel:SetTextColor(GREEN_FONT_COLOR.r, GREEN_FONT_COLOR.g, GREEN_FONT_COLOR.b);
  1838. self.PendingLabel:Show();
  1839. self.ExpirationTime:Hide();
  1840. self.CancelButton:Hide();
  1841. elseif ( appStatus == "invitedeclined" ) then
  1842. self.PendingLabel:SetText(LFG_LIST_APP_INVITE_DECLINED);
  1843. self.PendingLabel:SetTextColor(RED_FONT_COLOR.r, RED_FONT_COLOR.g, RED_FONT_COLOR.b);
  1844. self.PendingLabel:Show();
  1845. self.ExpirationTime:Hide();
  1846. self.CancelButton:Hide();
  1847. elseif ( isApplication and pendingStatus ~= "applied" ) then
  1848. self.PendingLabel:SetText(LFG_LIST_PENDING);
  1849. self.PendingLabel:SetTextColor(GREEN_FONT_COLOR.r, GREEN_FONT_COLOR.g, GREEN_FONT_COLOR.b);
  1850. self.PendingLabel:Show();
  1851. self.ExpirationTime:Show();
  1852. self.CancelButton:Show();
  1853. else
  1854. self.PendingLabel:Hide();
  1855. self.ExpirationTime:Hide();
  1856. self.CancelButton:Hide();
  1857. end
  1858. --Center justify if we're on more than one line
  1859. if ( self.PendingLabel:GetHeight() > 15 ) then
  1860. self.PendingLabel:SetJustifyH("CENTER");
  1861. else
  1862. self.PendingLabel:SetJustifyH("RIGHT");
  1863. end
  1864. --Change the anchor of the label depending on whether we have the expiration time
  1865. if ( self.ExpirationTime:IsShown() ) then
  1866. self.PendingLabel:SetPoint("RIGHT", self.ExpirationTime, "LEFT", -3, 0);
  1867. else
  1868. self.PendingLabel:SetPoint("RIGHT", self.ExpirationTime, "RIGHT", -3, 0);
  1869. end
  1870. self.expiration = GetTime() + appDuration;
  1871. local panel = self:GetParent():GetParent():GetParent();
  1872. local searchResultInfo = C_LFGList.GetSearchResultInfo(resultID);
  1873. local activityName = C_LFGList.GetActivityInfo(searchResultInfo.activityID);
  1874. self.resultID = resultID;
  1875. self.Selected:SetShown(panel.selectedResult == resultID and not isApplication and not searchResultInfo.isDelisted);
  1876. self.Highlight:SetShown(panel.selectedResult ~= resultID and not isApplication and not searchResultInfo.isDelisted);
  1877. local nameColor = NORMAL_FONT_COLOR;
  1878. local activityColor = GRAY_FONT_COLOR;
  1879. if ( searchResultInfo.isDelisted or isAppFinished ) then
  1880. nameColor = LFG_LIST_DELISTED_FONT_COLOR;
  1881. activityColor = LFG_LIST_DELISTED_FONT_COLOR;
  1882. elseif ( searchResultInfo.numBNetFriends > 0 or searchResultInfo.numCharFriends > 0 or searchResultInfo.numGuildMates > 0 ) then
  1883. nameColor = BATTLENET_FONT_COLOR;
  1884. end
  1885. self.Name:SetWidth(0);
  1886. self.Name:SetText(searchResultInfo.name);
  1887. self.Name:SetTextColor(nameColor.r, nameColor.g, nameColor.b);
  1888. self.ActivityName:SetText(activityName);
  1889. self.ActivityName:SetTextColor(activityColor.r, activityColor.g, activityColor.b);
  1890. self.VoiceChat:SetShown(searchResultInfo.voiceChat ~= "");
  1891. self.VoiceChat.tooltip = searchResultInfo.voiceChat;
  1892. local displayData = C_LFGList.GetSearchResultMemberCounts(resultID);
  1893. LFGListGroupDataDisplay_Update(self.DataDisplay, searchResultInfo.activityID, displayData, searchResultInfo.isDelisted);
  1894. local nameWidth = isApplication and 165 or 176;
  1895. if ( searchResultInfo.voiceChat ~= "" ) then
  1896. nameWidth = nameWidth - 22;
  1897. end
  1898. if ( self.Name:GetWidth() > nameWidth ) then
  1899. self.Name:SetWidth(nameWidth);
  1900. end
  1901. self.ActivityName:SetWidth(nameWidth);
  1902. local mouseFocus = GetMouseFocus();
  1903. if ( mouseFocus == self ) then
  1904. LFGListSearchEntry_OnEnter(self);
  1905. end
  1906. if ( mouseFocus == self.VoiceChat ) then
  1907. mouseFocus:GetScript("OnEnter")(mouseFocus);
  1908. end
  1909. if ( isApplication ) then
  1910. self:SetScript("OnUpdate", LFGListSearchEntry_UpdateExpiration);
  1911. LFGListSearchEntry_UpdateExpiration(self);
  1912. else
  1913. self:SetScript("OnUpdate", nil);
  1914. end
  1915. end
  1916. function LFGListSearchEntry_UpdateExpiration(self)
  1917. local duration = 0;
  1918. local now = GetTime();
  1919. if ( self.expiration and self.expiration > now ) then
  1920. duration = self.expiration - now;
  1921. end
  1922. local minutes = math.floor(duration / 60);
  1923. local seconds = duration % 60;
  1924. self.ExpirationTime:SetFormattedText("%d:%.2d", minutes, seconds);
  1925. end
  1926. function LFGListSearchEntry_OnEvent(self, event, ...)
  1927. if ( event == "LFG_LIST_SEARCH_RESULT_UPDATED" ) then
  1928. local id = ...;
  1929. if ( id == self.resultID ) then
  1930. LFGListSearchEntry_Update(self);
  1931. end
  1932. elseif ( event == "LFG_ROLE_CHECK_UPDATE" ) then
  1933. if ( self.resultID ) then
  1934. LFGListSearchEntry_Update(self);
  1935. end
  1936. end
  1937. end
  1938. function LFGListSearchEntry_OnClick(self, button)
  1939. local scrollFrame = self:GetParent():GetParent();
  1940. if ( button == "RightButton" ) then
  1941. PlaySound(SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_ON);
  1942. EasyMenu(LFGListUtil_GetSearchEntryMenu(self.resultID), LFGListFrameDropDown, self, 290, -2, "MENU");
  1943. elseif ( scrollFrame:GetParent().selectedResult ~= self.resultID and LFGListSearchPanelUtil_CanSelectResult(self.resultID) ) then
  1944. PlaySound(SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_ON);
  1945. LFGListSearchPanel_SelectResult(scrollFrame:GetParent(), self.resultID);
  1946. end
  1947. end
  1948. function LFGListSearchEntry_OnEnter(self)
  1949. GameTooltip:SetOwner(self, "ANCHOR_RIGHT", 25, 0);
  1950. local resultID = self.resultID;
  1951. LFGListUtil_SetSearchEntryTooltip(GameTooltip, resultID);
  1952. end
  1953. function LFGListSearchEntryUtil_GetFriendList(resultID)
  1954. local list = "";
  1955. local bNetFriends, charFriends, guildMates = C_LFGList.GetSearchResultFriends(resultID);
  1956. local displayedFirst = false;
  1957. --BNet friends
  1958. for i=1, #bNetFriends do
  1959. if ( displayedFirst ) then
  1960. list = list..PLAYER_LIST_DELIMITER;
  1961. else
  1962. displayedFirst = true;
  1963. end
  1964. list = list..FRIENDS_BNET_NAME_COLOR_CODE..bNetFriends[i]..FONT_COLOR_CODE_CLOSE;
  1965. end
  1966. --Character friends
  1967. for i=1, #charFriends do
  1968. if ( displayedFirst ) then
  1969. list = list..PLAYER_LIST_DELIMITER;
  1970. else
  1971. displayedFirst = true;
  1972. end
  1973. list = list..FRIENDS_WOW_NAME_COLOR_CODE..charFriends[i]..FONT_COLOR_CODE_CLOSE;
  1974. end
  1975. --Guild mates
  1976. for i=1, #guildMates do
  1977. if ( displayedFirst ) then
  1978. list = list..PLAYER_LIST_DELIMITER;
  1979. else
  1980. displayedFirst = true;
  1981. end
  1982. list = list..RGBTableToColorCode(ChatTypeInfo.GUILD)..guildMates[i]..FONT_COLOR_CODE_CLOSE;
  1983. end
  1984. return list;
  1985. end
  1986. -------------------------------------------------------
  1987. ----------Application dialog functions
  1988. -------------------------------------------------------
  1989. function LFGListApplicationDialog_OnLoad(self)
  1990. self:RegisterEvent("LFG_ROLE_UPDATE");
  1991. self.Description.EditBox:SetScript("OnEnterPressed", nop);
  1992. self.hideOnEscape = true;
  1993. end
  1994. function LFGListApplicationDialog_OnEvent(self, event)
  1995. if ( event == "LFG_ROLE_UPDATE" ) then
  1996. LFGListApplicationDialog_UpdateRoles(self);
  1997. end
  1998. end
  1999. function LFGListApplicationDialog_Show(self, resultID)
  2000. local searchResultInfo = C_LFGList.GetSearchResultInfo(resultID);
  2001. if ( searchResultInfo.activityID ~= self.activityID ) then
  2002. C_LFGList.ClearApplicationTextFields();
  2003. end
  2004. self.resultID = resultID;
  2005. self.activityID = searchResultInfo.activityID;
  2006. LFGListApplicationDialog_UpdateRoles(self);
  2007. StaticPopupSpecial_Show(self);
  2008. end
  2009. function LFGListApplicationDialog_UpdateRoles(self)
  2010. local availTank, availHealer, availDPS = C_LFGList.GetAvailableRoles();
  2011. local avail1, avail2, avail3;
  2012. if ( availTank ) then
  2013. avail1 = self.TankButton;
  2014. end
  2015. if ( availHealer ) then
  2016. if ( avail1 ) then
  2017. avail2 = self.HealerButton;
  2018. else
  2019. avail1 = self.HealerButton;
  2020. end
  2021. end
  2022. if ( availDPS ) then
  2023. if ( avail2 ) then
  2024. avail3 = self.DamagerButton;
  2025. elseif ( avail1 ) then
  2026. avail2 = self.DamagerButton;
  2027. else
  2028. avail1 = self.DamagerButton;
  2029. end
  2030. end
  2031. self.TankButton:SetShown(availTank);
  2032. self.HealerButton:SetShown(availHealer);
  2033. self.DamagerButton:SetShown(availDPS);
  2034. if ( avail3 ) then
  2035. avail1:ClearAllPoints();
  2036. avail1:SetPoint("TOPRIGHT", self, "TOP", -53, -35);
  2037. avail2:ClearAllPoints();
  2038. avail2:SetPoint("TOP", self, "TOP", 0, -35);
  2039. avail3:ClearAllPoints();
  2040. avail3:SetPoint("TOPLEFT", self, "TOP", 53, -35);
  2041. elseif ( avail2 ) then
  2042. avail1:ClearAllPoints();
  2043. avail1:SetPoint("TOPRIGHT", self, "TOP", -5, -35);
  2044. avail2:ClearAllPoints();
  2045. avail2:SetPoint("TOPLEFT", self, "TOP", 5, -35);
  2046. elseif ( avail1 ) then
  2047. avail1:ClearAllPoints();
  2048. avail1:SetPoint("TOP", self, "TOP", 0, -35);
  2049. end
  2050. local _, tank, healer, dps = GetLFGRoles();
  2051. self.TankButton.CheckButton:SetChecked(tank);
  2052. self.HealerButton.CheckButton:SetChecked(healer);
  2053. self.DamagerButton.CheckButton:SetChecked(dps);
  2054. LFGListApplicationDialog_UpdateValidState(self);
  2055. end
  2056. function LFGListApplicationDialog_UpdateValidState(self)
  2057. if ( ( self.TankButton:IsShown() and self.TankButton.CheckButton:GetChecked())
  2058. or ( self.HealerButton:IsShown() and self.HealerButton.CheckButton:GetChecked())
  2059. or ( self.DamagerButton:IsShown() and self.DamagerButton.CheckButton:GetChecked()) ) then
  2060. self.SignUpButton:Enable();
  2061. self.SignUpButton.errorText = nil;
  2062. else
  2063. self.SignUpButton:Disable();
  2064. self.SignUpButton.errorText = LFG_LIST_MUST_SELECT_ROLE;
  2065. end
  2066. end
  2067. function LFGListApplicationDialogSignUpButton_OnClick(button)
  2068. local dialog = button:GetParent();
  2069. PlaySound(SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_ON);
  2070. C_LFGList.ApplyToGroup(dialog.resultID, dialog.TankButton:IsShown() and dialog.TankButton.CheckButton:GetChecked(), dialog.HealerButton:IsShown() and dialog.HealerButton.CheckButton:GetChecked(), dialog.DamagerButton:IsShown() and dialog.DamagerButton.CheckButton:GetChecked());
  2071. StaticPopupSpecial_Hide(dialog);
  2072. end
  2073. function LFGListRoleButtonCheckButton_OnClick(self)
  2074. if ( self:GetChecked() ) then
  2075. PlaySound(SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_ON);
  2076. else
  2077. PlaySound(SOUNDKIT.IG_MAINMENU_OPTION_CHECKBOX_OFF);
  2078. end
  2079. local dialog = self:GetParent():GetParent();
  2080. local leader, tank, healer, dps = GetLFGRoles();
  2081. SetLFGRoles(leader, dialog.TankButton.CheckButton:GetChecked(), dialog.HealerButton.CheckButton:GetChecked(), dialog.DamagerButton.CheckButton:GetChecked());
  2082. end
  2083. -------------------------------------------------------
  2084. ----------Invite dialog functions
  2085. -------------------------------------------------------
  2086. function LFGListInviteDialog_OnLoad(self)
  2087. self:RegisterEvent("LFG_LIST_SEARCH_RESULTS_RECEIVED");
  2088. self:RegisterEvent("LFG_LIST_SEARCH_RESULT_UPDATED");
  2089. self:RegisterEvent("LFG_LIST_JOINED_GROUP");
  2090. self:RegisterEvent("PARTY_LEADER_CHANGED");
  2091. self:RegisterEvent("UNIT_CONNECTION");
  2092. end
  2093. function LFGListInviteDialog_OnEvent(self, event, ...)
  2094. if ( event == "LFG_LIST_SEARCH_RESULTS_RECEIVED" ) then
  2095. LFGListInviteDialog_CheckPending(self);
  2096. elseif ( event == "LFG_LIST_SEARCH_RESULT_UPDATED" ) then
  2097. local id = ...;
  2098. local _, status, pendingStatus = C_LFGList.GetApplicationInfo(id);
  2099. local empowered = LFGListUtil_IsAppEmpowered();
  2100. if ( self.resultID == id and not self.informational and (status ~= "invited" or not empowered) ) then
  2101. --Check if we need to hide the panel
  2102. StaticPopupSpecial_Hide(self);
  2103. LFGListInviteDialog_CheckPending(self);
  2104. elseif ( status == "invited" and not pendingStatus ) then
  2105. --Check if we need to show this result
  2106. LFGListInviteDialog_CheckPending(self);
  2107. end
  2108. elseif ( event == "PARTY_LEADER_CHANGED" ) then
  2109. --Check if we need to hide the current panel
  2110. if ( not LFGListUtil_IsAppEmpowered() and self:IsShown() and not self.informational ) then
  2111. StaticPopupSpecial_Hide(self);
  2112. end
  2113. --Check if we need to show any panels
  2114. LFGListInviteDialog_CheckPending(self);
  2115. elseif ( event == "LFG_LIST_JOINED_GROUP" ) then
  2116. if ( not LFGListUtil_IsAppEmpowered() ) then
  2117. --Show the informational dialog, regardless of whether we already had something up
  2118. local id, kstringGroupName = ...;
  2119. StaticPopupSpecial_Hide(self);
  2120. LFGListInviteDialog_Show(self, id, kstringGroupName);
  2121. end
  2122. elseif ( event == "UNIT_CONNECTION" ) then
  2123. LFGListInviteDialog_UpdateOfflineNotice(self);
  2124. end
  2125. end
  2126. function LFGListInviteDialog_CheckPending(self)
  2127. --If we're already showing one, don't replace it
  2128. if ( self:IsShown() ) then
  2129. return;
  2130. end
  2131. --If we're not empowered to make changes to applications, don't pop up anything.
  2132. if ( not LFGListUtil_IsAppEmpowered() ) then
  2133. return;
  2134. end
  2135. local apps = C_LFGList.GetApplications();
  2136. for i=1, #apps do
  2137. local id, status, pendingStatus = C_LFGList.GetApplicationInfo(apps[i]);
  2138. if ( status == "invited" and not pendingStatus ) then
  2139. LFGListInviteDialog_Show(self, apps[i]);
  2140. return;
  2141. end
  2142. end
  2143. end
  2144. function LFGListInviteDialog_Show(self, resultID, kstringGroupName)
  2145. local searchResultInfo = C_LFGList.GetSearchResultInfo(resultID);
  2146. local activityName = C_LFGList.GetActivityInfo(searchResultInfo.activityID);
  2147. local _, status, _, _, role = C_LFGList.GetApplicationInfo(resultID);
  2148. local informational = (status ~= "invited");
  2149. assert(not informational or status == "inviteaccepted");
  2150. self.resultID = resultID;
  2151. self.GroupName:SetText(kstringGroupName or searchResultInfo.name);
  2152. self.ActivityName:SetText(activityName);
  2153. self.Role:SetText(_G[role]);
  2154. self.RoleIcon:SetTexCoord(GetTexCoordsForRole(role));
  2155. self.Label:SetText(informational and LFG_LIST_JOINED_GROUP_NOTICE or LFG_LIST_INVITED_TO_GROUP);
  2156. self.informational = informational;
  2157. self.AcceptButton:SetShown(not informational);
  2158. self.DeclineButton:SetShown(not informational);
  2159. self.AcknowledgeButton:SetShown(informational);
  2160. if ( not informational and GroupHasOfflineMember(LE_PARTY_CATEGORY_HOME) ) then
  2161. self:SetHeight(250);
  2162. self.OfflineNotice:Show();
  2163. LFGListInviteDialog_UpdateOfflineNotice(self);
  2164. else
  2165. self:SetHeight(210);
  2166. self.OfflineNotice:Hide();
  2167. end
  2168. StaticPopupSpecial_Show(self);
  2169. PlaySound(SOUNDKIT.READY_CHECK);
  2170. FlashClientIcon();
  2171. end
  2172. function LFGListInviteDialog_UpdateOfflineNotice(self)
  2173. if ( GroupHasOfflineMember(LE_PARTY_CATEGORY_HOME) ) then
  2174. self.OfflineNotice:SetText(LFG_LIST_OFFLINE_MEMBER_NOTICE);
  2175. self.OfflineNotice:SetFontObject(GameFontRed);
  2176. else
  2177. self.OfflineNotice:SetText(LFG_LIST_OFFLINE_MEMBER_NOTICE_GONE);
  2178. self.OfflineNotice:SetFontObject(GameFontGreen);
  2179. end
  2180. end
  2181. function LFGListInviteDialog_Accept(self)
  2182. C_LFGList.AcceptInvite(self.resultID);
  2183. StaticPopupSpecial_Hide(self);
  2184. LFGListInviteDialog_CheckPending(self);
  2185. end
  2186. function LFGListInviteDialog_Decline(self)
  2187. C_LFGList.DeclineInvite(self.resultID);
  2188. StaticPopupSpecial_Hide(self);
  2189. LFGListInviteDialog_CheckPending(self);
  2190. end
  2191. function LFGListInviteDialog_Acknowledge(self)
  2192. StaticPopupSpecial_Hide(self);
  2193. LFGListInviteDialog_CheckPending(self);
  2194. end
  2195. -------------------------------------------------------
  2196. ----------Group Data Display functions
  2197. -------------------------------------------------------
  2198. function LFGListGroupDataDisplay_Update(self, activityID, displayData, disabled)
  2199. local fullName, shortName, categoryID, groupID, iLevel, filters, minLevel, maxPlayers, displayType = C_LFGList.GetActivityInfo(activityID);
  2200. if ( displayType == LE_LFG_LIST_DISPLAY_TYPE_ROLE_COUNT ) then
  2201. self.RoleCount:Show();
  2202. self.Enumerate:Hide();
  2203. self.PlayerCount:Hide();
  2204. LFGListGroupDataDisplayRoleCount_Update(self.RoleCount, displayData, disabled);
  2205. elseif ( displayType == LE_LFG_LIST_DISPLAY_TYPE_ROLE_ENUMERATE ) then
  2206. self.RoleCount:Hide();
  2207. self.Enumerate:Show();
  2208. self.PlayerCount:Hide();
  2209. LFGListGroupDataDisplayEnumerate_Update(self.Enumerate, maxPlayers, displayData, disabled, LFG_LIST_GROUP_DATA_ROLE_ORDER);
  2210. elseif ( displayType == LE_LFG_LIST_DISPLAY_TYPE_CLASS_ENUMERATE ) then
  2211. self.RoleCount:Hide();
  2212. self.Enumerate:Show();
  2213. self.PlayerCount:Hide();
  2214. LFGListGroupDataDisplayEnumerate_Update(self.Enumerate, maxPlayers, displayData, disabled, LFG_LIST_GROUP_DATA_CLASS_ORDER);
  2215. elseif ( displayType == LE_LFG_LIST_DISPLAY_TYPE_PLAYER_COUNT ) then
  2216. self.RoleCount:Hide();
  2217. self.Enumerate:Hide();
  2218. self.PlayerCount:Show();
  2219. LFGListGroupDataDisplayPlayerCount_Update(self.PlayerCount, displayData, disabled);
  2220. elseif ( displayType == LE_LFG_LIST_DISPLAY_TYPE_HIDE_ALL ) then
  2221. self.RoleCount:Hide();
  2222. self.Enumerate:Hide();
  2223. self.PlayerCount:Hide();
  2224. else
  2225. GMError("Unknown display type");
  2226. self.RoleCount:Hide();
  2227. self.Enumerate:Hide();
  2228. self.PlayerCount:Hide();
  2229. end
  2230. end
  2231. function LFGListGroupDataDisplayRoleCount_Update(self, displayData, disabled)
  2232. self.TankCount:SetText(displayData.TANK);
  2233. self.HealerCount:SetText(displayData.HEALER);
  2234. self.DamagerCount:SetText(displayData.DAMAGER);
  2235. --Update for the disabled state
  2236. local r = disabled and LFG_LIST_DELISTED_FONT_COLOR.r or HIGHLIGHT_FONT_COLOR.r;
  2237. local g = disabled and LFG_LIST_DELISTED_FONT_COLOR.g or HIGHLIGHT_FONT_COLOR.g;
  2238. local b = disabled and LFG_LIST_DELISTED_FONT_COLOR.b or HIGHLIGHT_FONT_COLOR.b;
  2239. self.TankCount:SetTextColor(r, g, b);
  2240. self.HealerCount:SetTextColor(r, g, b);
  2241. self.DamagerCount:SetTextColor(r, g, b);
  2242. self.TankIcon:SetDesaturated(disabled);
  2243. self.HealerIcon:SetDesaturated(disabled);
  2244. self.DamagerIcon:SetDesaturated(disabled);
  2245. self.TankIcon:SetAlpha(disabled and 0.5 or 0.70);
  2246. self.HealerIcon:SetAlpha(disabled and 0.5 or 0.70);
  2247. self.DamagerIcon:SetAlpha(disabled and 0.5 or 0.70);
  2248. end
  2249. function LFGListGroupDataDisplayEnumerate_Update(self, numPlayers, displayData, disabled, iconOrder)
  2250. --Show/hide the required icons
  2251. for i=1, #self.Icons do
  2252. if ( i > numPlayers ) then
  2253. self.Icons[i]:Hide();
  2254. else
  2255. self.Icons[i]:Show();
  2256. self.Icons[i]:SetDesaturated(disabled);
  2257. self.Icons[i]:SetAlpha(disabled and 0.5 or 1.0);
  2258. end
  2259. end
  2260. --Note that icons are numbered from right to left
  2261. local iconIndex = numPlayers;
  2262. for i=1, #iconOrder do
  2263. for j=1, displayData[iconOrder[i]] do
  2264. self.Icons[iconIndex]:SetAtlas(LFG_LIST_GROUP_DATA_ATLASES[iconOrder[i]], false);
  2265. iconIndex = iconIndex - 1;
  2266. if ( iconIndex < 1 ) then
  2267. return;
  2268. end
  2269. end
  2270. end
  2271. for i=1, iconIndex do
  2272. self.Icons[i]:SetAtlas("groupfinder-icon-emptyslot", false);
  2273. end
  2274. end
  2275. function LFGListGroupDataDisplayPlayerCount_Update(self, displayData, disabled)
  2276. local numPlayers = displayData.TANK + displayData.HEALER + displayData.DAMAGER + displayData.NOROLE;
  2277. local color = disabled and LFG_LIST_DELISTED_FONT_COLOR or HIGHLIGHT_FONT_COLOR;
  2278. self.Count:SetText(numPlayers);
  2279. self.Count:SetTextColor(color.r, color.g, color.b);
  2280. self.Icon:SetDesaturated(disabled);
  2281. self.Icon:SetAlpha(disabled and 0.5 or 1);
  2282. end
  2283. -------------------------------------------------------
  2284. ----------Edit Box functions
  2285. -------------------------------------------------------
  2286. function LFGListEditBox_AddToTabCategory(self, tabCategory)
  2287. self.tabCategory = tabCategory;
  2288. local cat = LFG_LIST_EDIT_BOX_TAB_CATEGORIES[tabCategory];
  2289. if ( not cat ) then
  2290. cat = {};
  2291. LFG_LIST_EDIT_BOX_TAB_CATEGORIES[tabCategory] = cat;
  2292. end
  2293. self.tabCategoryIndex = #cat+1;
  2294. cat[self.tabCategoryIndex] = self;
  2295. end
  2296. function LFGListEditBox_OnTabPressed(self)
  2297. if ( self.tabCategory ) then
  2298. local offset = IsShiftKeyDown() and -1 or 1;
  2299. local cat = LFG_LIST_EDIT_BOX_TAB_CATEGORIES[self.tabCategory];
  2300. if ( cat ) then
  2301. --It's times like this when I wish Lua was 0-based...
  2302. cat[((self.tabCategoryIndex - 1 + offset + #cat) % #cat) + 1]:SetFocus();
  2303. end
  2304. end
  2305. end
  2306. -------------------------------------------------------
  2307. ----------Requirement functions
  2308. -------------------------------------------------------
  2309. function LFGListRequirement_Validate(self, text)
  2310. if ( self.validateFunc ) then
  2311. self.warningText = self:validateFunc(text);
  2312. self.WarningFrame:SetShown(self.warningText);
  2313. self.CheckButton:SetShown(not self.warningText);
  2314. end
  2315. LFGListEntryCreation_UpdateValidState(self:GetParent());
  2316. end
  2317. -------------------------------------------------------
  2318. ----------Utility functions
  2319. -------------------------------------------------------
  2320. function LFGListUtil_AugmentWithBest(filters, categoryID, groupID, activityID)
  2321. local myNumMembers = math.max(GetNumGroupMembers(LE_PARTY_CATEGORY_HOME), 1);
  2322. local myItemLevel = GetAverageItemLevel();
  2323. if ( not activityID ) then
  2324. --Find the best activity by iLevel and recommended flag
  2325. local activities = C_LFGList.GetAvailableActivities(categoryID, groupID, filters);
  2326. local bestItemLevel, bestRecommended, bestCurrentArea, bestMinLevel, bestMaxPlayers;
  2327. for i=1, #activities do
  2328. local fullName, shortName, categoryID, groupID, iLevel, filters, minLevel, maxPlayers, displayType, orderIndex, useHonorLevel = C_LFGList.GetActivityInfo(activities[i]);
  2329. local isRecommended = bit.band(filters, LE_LFG_LIST_FILTER_RECOMMENDED) ~= 0;
  2330. local currentArea = C_LFGList.GetActivityInfoExpensive(activities[i]);
  2331. local usedItemLevel = myItemLevel;
  2332. local isBetter = false;
  2333. if ( not activityID ) then
  2334. isBetter = true;
  2335. elseif ( currentArea ~= bestCurrentArea ) then
  2336. isBetter = currentArea;
  2337. elseif ( bestRecommended ~= isRecommended ) then
  2338. isBetter = isRecommended;
  2339. elseif ( bestMinLevel ~= minLevel ) then
  2340. isBetter = minLevel > bestMinLevel;
  2341. elseif ( iLevel ~= bestItemLevel ) then
  2342. isBetter = (iLevel > bestItemLevel and iLevel <= usedItemLevel) or
  2343. (iLevel <= usedItemLevel and bestItemLevel > usedItemLevel) or
  2344. (iLevel < bestItemLevel and iLevel > usedItemLevel);
  2345. elseif ( (myNumMembers < maxPlayers) ~= (myNumMembers < bestMaxPlayers) ) then
  2346. isBetter = myNumMembers < maxPlayers;
  2347. end
  2348. if ( isBetter ) then
  2349. activityID = activities[i];
  2350. bestItemLevel = iLevel;
  2351. bestRecommended = isRecommended;
  2352. bestCurrentArea = currentArea;
  2353. bestMinLevel = minLevel;
  2354. bestMaxPlayers = maxPlayers;
  2355. end
  2356. end
  2357. end
  2358. assert(activityID);
  2359. --Update the categoryID and groupID with what we get from the activity
  2360. local _;
  2361. categoryID, groupID, _, filters = select(ACTIVITY_RETURN_VALUES.categoryID, C_LFGList.GetActivityInfo(activityID));
  2362. --Update the filters if needed
  2363. local _, separateRecommended = C_LFGList.GetCategoryInfo(categoryID);
  2364. if ( separateRecommended ) then
  2365. if ( bit.band(filters, LE_LFG_LIST_FILTER_RECOMMENDED) == 0 ) then
  2366. filters = LE_LFG_LIST_FILTER_NOT_RECOMMENDED;
  2367. else
  2368. filters = LE_LFG_LIST_FILTER_RECOMMENDED;
  2369. end
  2370. else
  2371. filters = 0;
  2372. end
  2373. return filters, categoryID, groupID, activityID;
  2374. end
  2375. function LFGListUtil_SetUpDropDown(context, dropdown, populateFunc, onClickFunc)
  2376. local onClick = function(self, ...)
  2377. onClickFunc(context, self.value, ...);
  2378. end
  2379. local initialize = function(self)
  2380. local info = UIDropDownMenu_CreateInfo();
  2381. info.func = onClick;
  2382. populateFunc(context, dropdown, info);
  2383. end
  2384. dropdown:SetScript("OnShow", function(self)
  2385. UIDropDownMenu_SetWidth(self, dropdown:GetWidth() - 50);
  2386. UIDropDownMenu_Initialize(self, initialize);
  2387. end);
  2388. UIDropDownMenu_JustifyText(dropdown, "LEFT");
  2389. UIDropDownMenu_SetAnchor(dropdown, -20, 7, "TOPRIGHT", dropdown, "BOTTOMRIGHT");
  2390. end
  2391. function LFGListUtil_ValidateLevelReq(self, text)
  2392. local myItemLevel = GetAverageItemLevel();
  2393. if ( text ~= "" and tonumber(text) > myItemLevel) then
  2394. return LFG_LIST_ILVL_ABOVE_YOURS;
  2395. end
  2396. end
  2397. function LFGListUtil_ValidateHonorLevelReq(self, text)
  2398. local myHonorLevel = UnitHonorLevel("player");
  2399. if (text ~= "" and tonumber(text) > myHonorLevel) then
  2400. return LFG_LIST_HONOR_LEVEL_ABOVE_YOURS;
  2401. end
  2402. end
  2403. -- TODO: Fix for Level Squish
  2404. function LFGListUtil_GetCurrentExpansion()
  2405. return GetExpansionForLevel(UnitLevel("player")) or LE_EXPANSION_LEVEL_CURRENT;
  2406. end
  2407. function LFGListUtil_GetDecoratedCategoryName(categoryName, filter, useColors)
  2408. if ( filter == 0 ) then
  2409. return categoryName;
  2410. end
  2411. local colorStart = "";
  2412. local colorEnd = "";
  2413. if ( useColors ) then
  2414. colorStart = "|cffffffff";
  2415. colorEnd = "|r";
  2416. end
  2417. local extraName = "";
  2418. if ( filter == LE_LFG_LIST_FILTER_NOT_RECOMMENDED ) then
  2419. extraName = LFG_LIST_LEGACY;
  2420. elseif ( filter == LE_LFG_LIST_FILTER_RECOMMENDED ) then
  2421. local exp = LFGListUtil_GetCurrentExpansion();
  2422. extraName = _G["EXPANSION_NAME"..exp];
  2423. end
  2424. return string.format(LFG_LIST_CATEGORY_FORMAT, categoryName, colorStart, extraName, colorEnd);
  2425. end
  2426. local roleRemainingKeyLookup = {
  2427. ["TANK"] = "TANK_REMAINING",
  2428. ["HEALER"] = "HEALER_REMAINING",
  2429. ["DAMAGER"] = "DAMAGER_REMAINING",
  2430. };
  2431. local function HasRemainingSlotsForLocalPlayerRole(lfgSearchResultID)
  2432. local roles = C_LFGList.GetSearchResultMemberCounts(lfgSearchResultID);
  2433. local playerRole = GetSpecializationRole(GetSpecialization());
  2434. return roles[roleRemainingKeyLookup[playerRole]] > 0;
  2435. end
  2436. function LFGListUtil_SortSearchResultsCB(searchResultID1, searchResultID2)
  2437. local searchResultInfo1 = C_LFGList.GetSearchResultInfo(searchResultID1);
  2438. local searchResultInfo2 = C_LFGList.GetSearchResultInfo(searchResultID2);
  2439. local hasRemainingRole1 = HasRemainingSlotsForLocalPlayerRole(searchResultID1);
  2440. local hasRemainingRole2 = HasRemainingSlotsForLocalPlayerRole(searchResultID2);
  2441. -- Groups with your current role available are preferred
  2442. if (hasRemainingRole1 ~= hasRemainingRole2) then
  2443. return hasRemainingRole1;
  2444. end
  2445. --If one has more friends, do that one first
  2446. if ( searchResultInfo1.numBNetFriends ~= searchResultInfo2.numBNetFriends ) then
  2447. return searchResultInfo1.numBNetFriends > searchResultInfo2.numBNetFriends;
  2448. end
  2449. if ( searchResultInfo1.numCharFriends ~= searchResultInfo2.numCharFriends ) then
  2450. return searchResultInfo1.numCharFriends > searchResultInfo2.numCharFriends;
  2451. end
  2452. if ( searchResultInfo1.numGuildMates ~= searchResultInfo2.numGuildMates ) then
  2453. return searchResultInfo1.numGuildMates > searchResultInfo2.numGuildMates;
  2454. end
  2455. --If we aren't sorting by anything else, just go by ID
  2456. return searchResultID1 < searchResultID2;
  2457. end
  2458. function LFGListUtil_SortSearchResults(results)
  2459. table.sort(results, LFGListUtil_SortSearchResultsCB);
  2460. end
  2461. function LFGListUtil_FilterSearchResults(results, filteredIDs)
  2462. for i, id in ipairs(filteredIDs) do
  2463. for j = #results, 1, -1 do
  2464. if ( results[j] == id ) then
  2465. tremove(results, j);
  2466. break;
  2467. end
  2468. end
  2469. end
  2470. end
  2471. function LFGListUtil_SortApplicantsCB(applicantID1, applicantID2)
  2472. local applicantInfo1 = C_LFGList.GetApplicantInfo(applicantID1);
  2473. local applicantInfo2 = C_LFGList.GetApplicantInfo(applicantID2);
  2474. --New items go to the bottom
  2475. if ( applicantInfo1.isNew ~= applicantInfo2.isNew ) then
  2476. return applicantInfo2.isNew;
  2477. end
  2478. return applicantInfo1.displayOrderID < applicantInfo2.displayOrderID;
  2479. end
  2480. function LFGListUtil_SortApplicants(applicants)
  2481. table.sort(applicants, LFGListUtil_SortApplicantsCB);
  2482. end
  2483. function LFGListUtil_IsAppEmpowered()
  2484. return not IsInGroup(LE_PARTY_CATEGORY_HOME) or UnitIsGroupLeader("player", LE_PARTY_CATEGORY_HOME);
  2485. end
  2486. function LFGListUtil_IsEntryEmpowered()
  2487. return UnitIsGroupLeader("player", LE_PARTY_CATEGORY_HOME) or UnitIsGroupAssistant("player", LE_PARTY_CATEGORY_HOME);
  2488. end
  2489. function LFGListUtil_CanSearchForGroup()
  2490. local hasActiveEntry = C_LFGList.HasActiveEntryInfo();
  2491. local canSearch = not hasActiveEntry or (LFGListUtil_IsAppEmpowered() or LFGListUtil_IsEntryEmpowered());
  2492. return canSearch;
  2493. end
  2494. function LFGListUtil_CanListGroup()
  2495. return LFGListUtil_IsAppEmpowered();
  2496. end
  2497. function LFGListUtil_AppendStatistic(label, value, title, lastTitle)
  2498. if ( title ~= lastTitle ) then
  2499. GameTooltip:AddLine(" ");
  2500. GameTooltip:AddLine(title, 1, 1, 1);
  2501. end
  2502. GameTooltip:AddLine(string.format(label, value));
  2503. end
  2504. local LFG_LIST_SEARCH_ENTRY_MENU = {
  2505. {
  2506. text = nil, --Group name goes here
  2507. isTitle = true,
  2508. notCheckable = true,
  2509. },
  2510. {
  2511. text = WHISPER_LEADER,
  2512. func = function(_, name) ChatFrame_SendTell(name); end,
  2513. notCheckable = true,
  2514. arg1 = nil, --Leader name goes here
  2515. disabled = nil, --Disabled if we don't have a leader name yet or you haven't applied
  2516. tooltipWhileDisabled = 1,
  2517. tooltipOnButton = 1,
  2518. tooltipTitle = nil, --The title to display on mouseover
  2519. tooltipText = nil, --The text to display on mouseover
  2520. },
  2521. {
  2522. text = LFG_LIST_REPORT_GROUP_FOR,
  2523. hasArrow = true,
  2524. notCheckable = true,
  2525. menuList = {
  2526. {
  2527. text = LFG_LIST_SPAM,
  2528. func = function(_, id)
  2529. CloseDropDownMenus();
  2530. C_LFGList.ReportSearchResult(id, "lfglistspam");
  2531. local panel = LFGListFrame.SearchPanel;
  2532. LFGListSearchPanel_AddFilteredID(panel, id);
  2533. LFGListSearchPanel_UpdateResultList(panel);
  2534. LFGListSearchPanel_UpdateResults(panel);
  2535. end,
  2536. arg1 = nil, --Search result ID goes here
  2537. notCheckable = true,
  2538. },
  2539. {
  2540. text = LFG_LIST_BAD_NAME,
  2541. func = function(_, id) C_LFGList.ReportSearchResult(id, "lfglistname"); end,
  2542. arg1 = nil, --Search result ID goes here
  2543. notCheckable = true,
  2544. },
  2545. {
  2546. text = LFG_LIST_BAD_DESCRIPTION,
  2547. func = function(_, id) C_LFGList.ReportSearchResult(id, "lfglistcomment"); end,
  2548. arg1 = nil, --Search reuslt ID goes here
  2549. notCheckable = true,
  2550. disabled = nil, --Disabled if the description is just an empty string
  2551. },
  2552. {
  2553. text = LFG_LIST_BAD_LEADER_NAME,
  2554. func = function(_, id) C_LFGList.ReportSearchResult(id, "badplayername"); end,
  2555. arg1 = nil, --Search reuslt ID goes here
  2556. notCheckable = true,
  2557. disabled = nil, --Disabled if we don't have a name for the leader
  2558. },
  2559. },
  2560. },
  2561. {
  2562. text = CANCEL,
  2563. notCheckable = true,
  2564. },
  2565. };
  2566. function LFGListUtil_GetSearchEntryMenu(resultID)
  2567. local searchResultInfo = C_LFGList.GetSearchResultInfo(resultID);
  2568. local _, appStatus, pendingStatus, appDuration = C_LFGList.GetApplicationInfo(resultID);
  2569. LFG_LIST_SEARCH_ENTRY_MENU[1].text = searchResultInfo.name;
  2570. LFG_LIST_SEARCH_ENTRY_MENU[2].arg1 = searchResultInfo.leaderName;
  2571. local applied = (appStatus == "applied" or appStatus == "invited");
  2572. LFG_LIST_SEARCH_ENTRY_MENU[2].disabled = not searchResultInfo.leaderName;
  2573. LFG_LIST_SEARCH_ENTRY_MENU[2].tooltipTitle = (not applied) and WHISPER
  2574. LFG_LIST_SEARCH_ENTRY_MENU[2].tooltipText = (not applied) and LFG_LIST_MUST_SIGN_UP_TO_WHISPER;
  2575. LFG_LIST_SEARCH_ENTRY_MENU[3].menuList[1].arg1 = resultID;
  2576. LFG_LIST_SEARCH_ENTRY_MENU[3].menuList[2].arg1 = resultID;
  2577. LFG_LIST_SEARCH_ENTRY_MENU[3].menuList[3].arg1 = resultID;
  2578. LFG_LIST_SEARCH_ENTRY_MENU[3].menuList[3].disabled = (searchResultInfo.comment == "");
  2579. LFG_LIST_SEARCH_ENTRY_MENU[3].menuList[4].arg1 = resultID;
  2580. LFG_LIST_SEARCH_ENTRY_MENU[3].menuList[4].disabled = not searchResultInfo.leaderName;
  2581. return LFG_LIST_SEARCH_ENTRY_MENU;
  2582. end
  2583. local LFG_LIST_APPLICANT_MEMBER_MENU = {
  2584. {
  2585. text = nil, --Player name goes here
  2586. isTitle = true,
  2587. notCheckable = true,
  2588. },
  2589. {
  2590. text = WHISPER,
  2591. func = function(_, name) ChatFrame_SendTell(name); end,
  2592. notCheckable = true,
  2593. arg1 = nil, --Player name goes here
  2594. disabled = nil, --Disabled if we don't have a name yet
  2595. },
  2596. {
  2597. text = LFG_LIST_REPORT_FOR,
  2598. hasArrow = true,
  2599. notCheckable = true,
  2600. menuList = {
  2601. {
  2602. text = LFG_LIST_BAD_PLAYER_NAME,
  2603. notCheckable = true,
  2604. func = function(_, id, memberIdx) C_LFGList.ReportApplicant(id, "badplayername", memberIdx); end,
  2605. arg1 = nil, --Applicant ID goes here
  2606. arg2 = nil, --Applicant Member index goes here
  2607. },
  2608. {
  2609. text = LFG_LIST_BAD_DESCRIPTION,
  2610. notCheckable = true,
  2611. func = function(_, id) C_LFGList.ReportApplicant(id, "lfglistappcomment"); end,
  2612. arg1 = nil, --Applicant ID goes here
  2613. },
  2614. },
  2615. },
  2616. {
  2617. text = IGNORE_PLAYER,
  2618. notCheckable = true,
  2619. func = function(_, name, applicantID) C_FriendList.AddIgnore(name); C_LFGList.DeclineApplicant(applicantID); end,
  2620. arg1 = nil, --Player name goes here
  2621. arg2 = nil, --Applicant ID goes here
  2622. disabled = nil, --Disabled if we don't have a name yet
  2623. },
  2624. {
  2625. text = CANCEL,
  2626. notCheckable = true,
  2627. },
  2628. };
  2629. function LFGListUtil_GetApplicantMemberMenu(applicantID, memberIdx)
  2630. local name, class, localizedClass, level, itemLevel, honorLevel, tank, healer, damage, assignedRole = C_LFGList.GetApplicantMemberInfo(applicantID, memberIdx);
  2631. local applicantInfo = C_LFGList.GetApplicantInfo(applicantID);
  2632. LFG_LIST_APPLICANT_MEMBER_MENU[1].text = name or " ";
  2633. LFG_LIST_APPLICANT_MEMBER_MENU[2].arg1 = name;
  2634. LFG_LIST_APPLICANT_MEMBER_MENU[2].disabled = not name or (applicantInfo.applicationStatus ~= "applied" and applicantInfo.applicationStatus ~= "invited");
  2635. LFG_LIST_APPLICANT_MEMBER_MENU[3].menuList[1].arg1 = applicantID;
  2636. LFG_LIST_APPLICANT_MEMBER_MENU[3].menuList[1].arg2 = memberIdx;
  2637. LFG_LIST_APPLICANT_MEMBER_MENU[3].menuList[2].arg1 = applicantID;
  2638. LFG_LIST_APPLICANT_MEMBER_MENU[3].menuList[2].disabled = (applicantInfo.comment == "");
  2639. LFG_LIST_APPLICANT_MEMBER_MENU[4].arg1 = name;
  2640. LFG_LIST_APPLICANT_MEMBER_MENU[4].arg2 = applicantID;
  2641. LFG_LIST_APPLICANT_MEMBER_MENU[4].disabled = not name;
  2642. return LFG_LIST_APPLICANT_MEMBER_MENU;
  2643. end
  2644. function LFGListUtil_InitializeLangaugeFilter(dropdown)
  2645. local info = UIDropDownMenu_CreateInfo();
  2646. local languages = C_LFGList.GetAvailableLanguageSearchFilter();
  2647. local enabled = C_LFGList.GetLanguageSearchFilter();
  2648. local defaults = C_LFGList.GetDefaultLanguageSearchFilter();
  2649. local entry = UIDropDownMenu_CreateInfo();
  2650. for i=1, #languages do
  2651. local lang = languages[i];
  2652. entry.text = _G["LFG_LIST_LANGUAGE_"..string.upper(lang)];
  2653. entry.checked = enabled[lang] or defaults[lang];
  2654. entry.disabled = defaults[lang];
  2655. entry.isNotRadio = true;
  2656. entry.keepShownOnClick = true;
  2657. entry.func = function(self,_,_,checked) enabled[lang] = checked; C_LFGList.SaveLanguageSearchFilter(enabled); end
  2658. UIDropDownMenu_AddButton(entry);
  2659. end
  2660. end
  2661. function LFGListUtil_OpenBestWindow(toggle)
  2662. local func = toggle and PVEFrame_ToggleFrame or PVEFrame_ShowFrame;
  2663. local activeEntryInfo = C_LFGList.GetActiveEntryInfo();
  2664. if ( activeEntryInfo ) then
  2665. --Open to the window of our active activity
  2666. local fullName, shortName, categoryID, groupID, iLevel, filters = C_LFGList.GetActivityInfo(activeEntryInfo.activityID);
  2667. if ( bit.band(filters, LE_LFG_LIST_FILTER_PVE) ~= 0 ) then
  2668. func("GroupFinderFrame", "LFGListPVEStub");
  2669. else
  2670. func("PVPUIFrame", "LFGListPVPStub");
  2671. end
  2672. else
  2673. --Open to the last window we had open
  2674. if ( bit.band(LFGListFrame.baseFilters, LE_LFG_LIST_FILTER_PVE) ~= 0 ) then
  2675. func("GroupFinderFrame", "LFGListPVEStub");
  2676. else
  2677. func("PVPUIFrame", "LFGListPVPStub");
  2678. end
  2679. end
  2680. end
  2681. function LFGListUtil_SortActivitiesByRelevancyCB(activityID1, activityID2)
  2682. local fullName1, _, _, _, iLevel1, _, minLevel1 = C_LFGList.GetActivityInfo(activityID1);
  2683. local fullName2, _, _, _, iLevel2, _, minLevel2 = C_LFGList.GetActivityInfo(activityID2);
  2684. if ( minLevel1 ~= minLevel2 ) then
  2685. return minLevel1 > minLevel2;
  2686. elseif ( iLevel1 ~= iLevel2 ) then
  2687. local myILevel = GetAverageItemLevel();
  2688. if ((iLevel1 <= myILevel) ~= (iLevel2 <= myILevel) ) then
  2689. --If one is below our item level and the other above, choose the one we meet
  2690. return iLevel1 < myILevel;
  2691. else
  2692. --If both are above or both are below, choose the one closest to our iLevel
  2693. return math.abs(iLevel1 - myILevel) < math.abs(iLevel2 - myILevel);
  2694. end
  2695. else
  2696. return strcmputf8i(fullName1, fullName2) < 0;
  2697. end
  2698. end
  2699. function LFGListUtil_SortActivitiesByRelevancy(activities)
  2700. table.sort(activities, LFGListUtil_SortActivitiesByRelevancyCB);
  2701. end
  2702. LFG_LIST_ACTIVE_QUEUE_MESSAGE_EVENTS = {
  2703. "LFG_LIST_ACTIVE_ENTRY_UPDATE",
  2704. "LFG_LIST_SEARCH_RESULT_UPDATED",
  2705. "UPDATE_BATTLEFIELD_STATUS",
  2706. "LFG_UPDATE",
  2707. "LFG_ROLE_CHECK_UPDATE",
  2708. "LFG_PROPOSAL_UPDATE",
  2709. "LFG_PROPOSAL_FAILED",
  2710. "LFG_PROPOSAL_SUCCEEDED",
  2711. "LFG_PROPOSAL_SHOW",
  2712. "LFG_QUEUE_STATUS_UPDATE",
  2713. };
  2714. function LFGListUtil_GetActiveQueueMessage(isApplication)
  2715. --Check for applications if we're trying to list
  2716. if ( not isApplication and select(2,C_LFGList.GetNumApplications()) > 0 ) then
  2717. return CANNOT_DO_THIS_WITH_LFGLIST_APP;
  2718. end
  2719. --Check for listings if we have an application
  2720. if ( isApplication and C_LFGList.HasActiveEntryInfo() ) then
  2721. return CANNOT_DO_THIS_WHILE_LFGLIST_LISTED;
  2722. end
  2723. --Check all LFG categories
  2724. for category=1, NUM_LE_LFG_CATEGORYS do
  2725. local mode = GetLFGMode(category);
  2726. if ( mode ) then
  2727. if ( mode == "lfgparty" ) then
  2728. return CANNOT_DO_THIS_IN_LFG_PARTY;
  2729. elseif ( mode == "rolecheck" or (mode and not isApplication) ) then
  2730. return CANNOT_DO_THIS_IN_PVE_QUEUE;
  2731. end
  2732. end
  2733. end
  2734. --Check PvP role check
  2735. local inProgress, _, _, _, _, isBattleground = GetLFGRoleUpdate();
  2736. if ( inProgress ) then
  2737. return isBattleground and CANNOT_DO_THIS_WHILE_PVP_QUEUING or CANNOT_DO_THIS_WHILE_PVE_QUEUING;
  2738. end
  2739. for i=1, GetMaxBattlefieldID() do
  2740. local status, mapName, teamSize, registeredMatch, suspend = GetBattlefieldStatus(i);
  2741. if ( status and status ~= "none" ) then
  2742. return CANNOT_DO_THIS_IN_BATTLEGROUND;
  2743. end
  2744. end
  2745. end
  2746. local LFG_LIST_INACTIVE_STATUSES = {
  2747. cancelled = true,
  2748. failed = true,
  2749. declined = true,
  2750. timedout = true,
  2751. invitedeclined = true,
  2752. }
  2753. function LFGListUtil_IsStatusInactive(status)
  2754. return LFG_LIST_INACTIVE_STATUSES[status];
  2755. end
  2756. function LFGListUtil_SetAutoAccept(autoAccept)
  2757. local activeEntryInfo = C_LFGList.GetActiveEntryInfo();
  2758. if activeEntryInfo then
  2759. C_LFGList.CopyActiveEntryInfoToCreationFields();
  2760. C_LFGList.UpdateListing(activeEntryInfo.activityID, activeEntryInfo.requiredItemLevel, activeEntryInfo.requiredHonorLevel, autoAccept, activeEntryInfo.privateGroup, activeEntryInfo.questID);
  2761. end
  2762. end
  2763. LFG_LIST_UTIL_SUPPRESS_AUTO_ACCEPT_LINE = 1;
  2764. LFG_LIST_UTIL_ALLOW_AUTO_ACCEPT_LINE = 2;
  2765. function LFGListUtil_SetSearchEntryTooltip(tooltip, resultID, autoAcceptOption)
  2766. local searchResultInfo = C_LFGList.GetSearchResultInfo(resultID);
  2767. local activityName, shortName, categoryID, groupID, minItemLevel, filters, minLevel, maxPlayers, displayType, _, useHonorLevel = C_LFGList.GetActivityInfo(searchResultInfo.activityID);
  2768. local memberCounts = C_LFGList.GetSearchResultMemberCounts(resultID);
  2769. tooltip:SetText(searchResultInfo.name, 1, 1, 1, true);
  2770. tooltip:AddLine(activityName);
  2771. if ( searchResultInfo.comment and searchResultInfo.comment == "" and searchResultInfo.questID ) then
  2772. searchResultInfo.comment = LFGListUtil_GetQuestDescription(searchResultInfo.questID);
  2773. end
  2774. if ( searchResultInfo.comment ~= "" ) then
  2775. tooltip:AddLine(string.format(LFG_LIST_COMMENT_FORMAT, searchResultInfo.comment), LFG_LIST_COMMENT_FONT_COLOR.r, LFG_LIST_COMMENT_FONT_COLOR.g, LFG_LIST_COMMENT_FONT_COLOR.b, true);
  2776. end
  2777. tooltip:AddLine(" ");
  2778. if ( searchResultInfo.requiredItemLevel > 0 ) then
  2779. tooltip:AddLine(string.format(LFG_LIST_TOOLTIP_ILVL, searchResultInfo.requiredItemLevel));
  2780. end
  2781. if ( useHonorLevel and searchResultInfo.requiredHonorLevel > 0 ) then
  2782. tooltip:AddLine(string.format(LFG_LIST_TOOLTIP_HONOR_LEVEL, searchResultInfo.requiredHonorLevel));
  2783. end
  2784. if ( searchResultInfo.voiceChat ~= "" ) then
  2785. tooltip:AddLine(string.format(LFG_LIST_TOOLTIP_VOICE_CHAT, searchResultInfo.voiceChat), nil, nil, nil, true);
  2786. end
  2787. if ( searchResultInfo.requiredItemLevel > 0 or (useHonorLevel and searchResultInfo.requiredHonorLevel > 0) or searchResultInfo.voiceChat ~= "" ) then
  2788. tooltip:AddLine(" ");
  2789. end
  2790. if ( searchResultInfo.leaderName ) then
  2791. tooltip:AddLine(string.format(LFG_LIST_TOOLTIP_LEADER, searchResultInfo.leaderName));
  2792. end
  2793. if ( searchResultInfo.age > 0 ) then
  2794. tooltip:AddLine(string.format(LFG_LIST_TOOLTIP_AGE, SecondsToTime(searchResultInfo.age, false, false, 1, false)));
  2795. end
  2796. if ( searchResultInfo.leaderName or searchResultInfo.age > 0 ) then
  2797. tooltip:AddLine(" ");
  2798. end
  2799. if ( displayType == LE_LFG_LIST_DISPLAY_TYPE_CLASS_ENUMERATE ) then
  2800. tooltip:AddLine(string.format(LFG_LIST_TOOLTIP_MEMBERS_SIMPLE, searchResultInfo.numMembers));
  2801. for i=1, searchResultInfo.numMembers do
  2802. local role, class, classLocalized = C_LFGList.GetSearchResultMemberInfo(resultID, i);
  2803. local classColor = RAID_CLASS_COLORS[class] or NORMAL_FONT_COLOR;
  2804. tooltip:AddLine(string.format(LFG_LIST_TOOLTIP_CLASS_ROLE, classLocalized, _G[role]), classColor.r, classColor.g, classColor.b);
  2805. end
  2806. else
  2807. tooltip:AddLine(string.format(LFG_LIST_TOOLTIP_MEMBERS, searchResultInfo.numMembers, memberCounts.TANK, memberCounts.HEALER, memberCounts.DAMAGER));
  2808. end
  2809. if ( searchResultInfo.numBNetFriends + searchResultInfo.numCharFriends + searchResultInfo.numGuildMates > 0 ) then
  2810. tooltip:AddLine(" ");
  2811. tooltip:AddLine(LFG_LIST_TOOLTIP_FRIENDS_IN_GROUP);
  2812. tooltip:AddLine(LFGListSearchEntryUtil_GetFriendList(resultID), 1, 1, 1, true);
  2813. end
  2814. local completedEncounters = C_LFGList.GetSearchResultEncounterInfo(resultID);
  2815. if ( completedEncounters and #completedEncounters > 0 ) then
  2816. tooltip:AddLine(" ");
  2817. tooltip:AddLine(LFG_LIST_BOSSES_DEFEATED);
  2818. for i=1, #completedEncounters do
  2819. tooltip:AddLine(completedEncounters[i], RED_FONT_COLOR.r, RED_FONT_COLOR.g, RED_FONT_COLOR.b);
  2820. end
  2821. end
  2822. autoAcceptOption = autoAcceptOption or LFG_LIST_UTIL_ALLOW_AUTO_ACCEPT_LINE;
  2823. if autoAcceptOption == LFG_LIST_UTIL_ALLOW_AUTO_ACCEPT_LINE and searchResultInfo.autoAccept then
  2824. tooltip:AddLine(" ");
  2825. tooltip:AddLine(LFG_LIST_TOOLTIP_AUTO_ACCEPT, LIGHTBLUE_FONT_COLOR:GetRGB());
  2826. end
  2827. if ( searchResultInfo.isDelisted ) then
  2828. tooltip:AddLine(" ");
  2829. tooltip:AddLine(LFG_LIST_ENTRY_DELISTED, RED_FONT_COLOR.r, RED_FONT_COLOR.g, RED_FONT_COLOR.b, true);
  2830. end
  2831. tooltip:Show();
  2832. end
  2833. function LFGListUtil_GetQuestCategoryData(questID)
  2834. -- Do not allow searches if the quest name cannot be looked up.
  2835. local questName = QuestUtils_GetQuestName(questID);
  2836. if not questName then
  2837. return;
  2838. end
  2839. local activityID = C_LFGList.GetActivityIDForQuestID(questID);
  2840. if activityID then
  2841. local fullName, shortName, categoryID, groupID, iLevel, filters, minLevel, maxPlayers, displayType = C_LFGList.GetActivityInfo(activityID);
  2842. -- NOTE: There's an issue where filters will actually contain ALL of the filters for the given activity.
  2843. -- This portion of the UI only cares about the filters for specific categories that get updated when the category buttons are added,
  2844. -- and furthermore only cares about them when we're separating a single category into recommended and non-recommended.
  2845. -- The baseFilters on the frame contain the rest of the required filters.
  2846. -- To solve this so that category selection can be properly driven from the API, only use the filters that would be present on the button.
  2847. -- Otherwise the selection will not work, and it won't be possible to create a group automatically.
  2848. local _, separateRecommended = C_LFGList.GetCategoryInfo(categoryID);
  2849. if separateRecommended then
  2850. if bit.bor(filters, LE_LFG_LIST_FILTER_RECOMMENDED) then
  2851. filters = LE_LFG_LIST_FILTER_RECOMMENDED;
  2852. elseif bit.bor(filters, LE_LFG_LIST_FILTER_NOT_RECOMMENDED) then
  2853. filters = LE_LFG_LIST_FILTER_NOT_RECOMMENDED;
  2854. else
  2855. filters = 0;
  2856. end
  2857. else
  2858. filters = 0;
  2859. end
  2860. return activityID, categoryID, filters, questName;
  2861. end
  2862. end
  2863. function LFGListUtil_FindQuestGroup(questID, isFromGreenEyeButton)
  2864. if C_LFGList.HasActiveEntryInfo() then
  2865. if LFGListUtil_CanListGroup() then
  2866. StaticPopup_Show("PREMADE_GROUP_SEARCH_DELIST_WARNING", nil, nil, questID);
  2867. else
  2868. LFGListUtil_OpenBestWindow();
  2869. end
  2870. else
  2871. LFGListFrame_BeginFindQuestGroup(LFGListFrame, questID, isFromGreenEyeButton);
  2872. end
  2873. end
  2874. function LFGListUtil_GetQuestDescription(questID)
  2875. local descriptionFormat = AUTO_GROUP_CREATION_NORMAL_QUEST;
  2876. if ( QuestUtils_IsQuestWorldQuest(questID) ) then
  2877. descriptionFormat = AUTO_GROUP_CREATION_WORLD_QUEST;
  2878. end
  2879. return descriptionFormat:format(QuestUtils_GetQuestName(questID));
  2880. end