LFGList.lua

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