--Layout consts, defining the widths of the list's columns as provided by design-- ZO_KEYBOARD_GROUP_LIST_PADDING_X = 5 ZO_KEYBOARD_GROUP_LIST_LEADER_WIDTH = 35 ZO_KEYBOARD_GROUP_LIST_NAME_WIDTH = 210 - ZO_KEYBOARD_GROUP_LIST_PADDING_X ZO_KEYBOARD_GROUP_LIST_LEADER_AND_NAME_WIDTH = ZO_KEYBOARD_GROUP_LIST_LEADER_WIDTH + ZO_KEYBOARD_GROUP_LIST_NAME_WIDTH ZO_KEYBOARD_GROUP_LIST_ZONE_WIDTH = 130 - ZO_KEYBOARD_GROUP_LIST_PADDING_X ZO_KEYBOARD_GROUP_LIST_CLASS_WIDTH = 75 - ZO_KEYBOARD_GROUP_LIST_PADDING_X ZO_KEYBOARD_GROUP_LIST_LEVEL_WIDTH = 80 - ZO_KEYBOARD_GROUP_LIST_PADDING_X ZO_KEYBOARD_GROUP_LIST_ROLES_WIDTH = 80 - ZO_KEYBOARD_GROUP_LIST_PADDING_X ---------------------------------- --Group List Keyboard ---------------------------------- local ZO_GroupList_Keyboard = ZO_Object.MultiSubclass(ZO_SortFilterList, ZO_SocialListDirtyLogic_Shared) local GROUP_DATA = 1 function ZO_GroupList_Keyboard:New(...) local manager = ZO_Object.New(self) manager:Initialize(...) return manager end function ZO_GroupList_Keyboard:Initialize(control) ZO_SortFilterList.InitializeSortFilterList(self, control) self.noGroupRow = control:GetNamedChild("NoGroupRow") self:InitializeKeybindDescriptors() control:SetHandler("OnEffectivelyHidden", function() self:OnEffectivelyHidden() end) self.difficultyControl = control:GetNamedChild("VeteranDifficultySettings") ZO_ScrollList_Initialize(self.list) ZO_ScrollList_AddDataType(self.list, GROUP_DATA, "ZO_GroupListRow", 30, function(control, data) self:SetupGroupEntry(control, data) end) self.headers = {} local headersParent = GetControl(control, "Headers") local numHeaders = headersParent:GetNumChildren() for i = 1, numHeaders do self.headers[i] = headersParent:GetChild(i) end ZO_ScrollList_EnableHighlight(self.list, "ZO_ThinListHighlight") GROUP_LIST_FRAGMENT = ZO_FadeSceneFragment:New(control) GROUP_LIST_FRAGMENT:RegisterCallback("StateChange", function(oldState, newState) if newState == SCENE_FRAGMENT_SHOWING then KEYBIND_STRIP:AddKeybindButtonGroup(self.keybindStripDescriptor) if self.difficultyControl.refreshFunction then self.difficultyControl.refreshFunction() end elseif newState == SCENE_FRAGMENT_SHOWN then self:RefreshData() TriggerTutorial(TUTORIAL_TRIGGER_YOUR_GROUP_OPENED) GROUP_LIST_FRAGMENT:FireCallbacks("OnGroupMenuShown") elseif newState == SCENE_FRAGMENT_HIDDEN then KEYBIND_STRIP:RemoveKeybindButtonGroup(self.keybindStripDescriptor) end end) self:InitializeDirtyLogic(GROUP_LIST_FRAGMENT) self.activeColor = ZO_ColorDef:New(GetInterfaceColor(INTERFACE_COLOR_TYPE_TEXT_COLORS, INTERFACE_TEXT_COLOR_NORMAL)) self.inactiveColor = ZO_ColorDef:New(GetInterfaceColor(INTERFACE_COLOR_TYPE_TEXT_COLORS, INTERFACE_TEXT_COLOR_DISABLED)) GROUP_LIST_MANAGER:AddList(self) local groupCategoryData = { priority = ZO_ACTIVITY_FINDER_SORT_PRIORITY.GROUP, name = GetString(SI_MAIN_MENU_GROUP), categoryFragment = GROUP_LIST_FRAGMENT, normalIcon = "EsoUI/Art/LFG/LFG_indexIcon_group_up.dds", pressedIcon = "EsoUI/Art/LFG/LFG_indexIcon_group_down.dds", mouseoverIcon = "EsoUI/Art/LFG/LFG_indexIcon_group_over.dds", } GROUP_MENU_KEYBOARD:AddCategory(groupCategoryData) local function OnUpdateGroupStatus() if GROUP_LIST_FRAGMENT:IsShowing() then KEYBIND_STRIP:UpdateKeybindButtonGroup(self.keybindStripDescriptor) end end ZO_ACTIVITY_FINDER_ROOT_MANAGER:RegisterCallback("OnUpdateGroupStatus", OnUpdateGroupStatus) end function ZO_GroupList_Keyboard:InitializeKeybindDescriptors() self.keybindStripDescriptor = { -- Invite to Group { alignment = KEYBIND_STRIP_ALIGN_CENTER, name = GetString(SI_GROUP_WINDOW_INVITE_PLAYER), keybind = "UI_SHORTCUT_PRIMARY", callback = function() ZO_Dialogs_ShowDialog("GROUP_INVITE") end, visible = function() local playerIsGrouped, playerIsLeader, groupSize = ZO_ACTIVITY_FINDER_ROOT_MANAGER:GetGroupStatus() return IsGroupModificationAvailable() and (not playerIsGrouped or (playerIsLeader and groupSize < MAX_GROUP_SIZE_THRESHOLD)) end }, -- Whisper { alignment = KEYBIND_STRIP_ALIGN_RIGHT, name = GetString(SI_SOCIAL_LIST_PANEL_WHISPER), keybind = "UI_SHORTCUT_SECONDARY", callback = function() local data = ZO_ScrollList_GetData(self.mouseOverRow) StartChatInput("", CHAT_CHANNEL_WHISPER, data.characterName) end, visible = function() if(self.mouseOverRow and IsChatSystemAvailableForCurrentPlatform()) then local data = ZO_ScrollList_GetData(self.mouseOverRow) return not data.isPlayer and data.characterName and data.online end return false end }, -- Ready Check { alignment = KEYBIND_STRIP_ALIGN_CENTER, name = GetString(SI_GROUP_LIST_READY_CHECK_BIND), keybind = "UI_SHORTCUT_TERTIARY", callback = ZO_SendReadyCheck, visible = function() -- GROUP_ELECTION_TYPE_GENERIC_UNANIMOUS matches what ZO_SendReadyCheck uses local expectedResult = GetExpectedGroupElectionResult(GROUP_ELECTION_TYPE_GENERIC_UNANIMOUS) return expectedResult ~= GROUP_ELECTION_FAILURE_NOT_GROUPED and expectedResult ~= GROUP_ELECTION_FAILURE_IN_BATTLEGROUND end, }, -- Leave Group { alignment = KEYBIND_STRIP_ALIGN_CENTER, name = GetString(SI_GROUP_LEAVE), keybind = "UI_SHORTCUT_NEGATIVE", callback = function() ZO_Dialogs_ShowDialog("GROUP_LEAVE_DIALOG") end, visible = function() return self.groupSize and self.groupSize > 0 end }, -- Leave Instance { alignment = KEYBIND_STRIP_ALIGN_CENTER, name = GetString(SI_GROUP_MENU_LEAVE_INSTANCE_KEYBIND), keybind = "UI_SHORTCUT_QUATERNARY", callback = function() ZO_Dialogs_ShowDialog("INSTANCE_LEAVE_DIALOG") end, visible = CanExitInstanceImmediately }, } end function ZO_GroupList_Keyboard:OnEffectivelyHidden() ZO_Dialogs_ReleaseDialog("GROUP_INVITE") end function ZO_GroupList_Keyboard:GroupListRow_OnMouseUp(control, button, upInside) if(button == MOUSE_BUTTON_INDEX_RIGHT and upInside) then ClearMenu() local data = ZO_ScrollList_GetData(control) if data then if data.isPlayer then AddMenuItem(GetString(SI_GROUP_LIST_MENU_LEAVE_GROUP), function() ZO_Dialogs_ShowDialog("GROUP_LEAVE_DIALOG") end) elseif data.online then if IsChatSystemAvailableForCurrentPlatform() then AddMenuItem(GetString(SI_SOCIAL_LIST_PANEL_WHISPER), function() StartChatInput("", CHAT_CHANNEL_WHISPER, data.characterName) end) end AddMenuItem(GetString(SI_SOCIAL_MENU_VISIT_HOUSE), function() JumpToHouse(data.displayName) end) if not ZO_IsTributeLocked() then AddMenuItem(GetString(SI_SOCIAL_MENU_TRIBUTE_INVITE), function() InviteToTributeByDisplayName(data.displayName) end) end AddMenuItem(GetString(SI_SOCIAL_MENU_JUMP_TO_PLAYER), function() JumpToGroupMember(data.characterName) end) end if not data.isPlayer and not IsFriend(data.displayName) and not IsIgnored(data.displayName) then AddMenuItem(GetString(SI_SOCIAL_MENU_ADD_FRIEND), function() ZO_Dialogs_ShowDialog("REQUEST_FRIEND", { name = data.displayName }) end) end if IsGroupModificationAvailable() then local modicationRequiresVoting = DoesGroupModificationRequireVote() if self.playerIsLeader then if data.isPlayer then if not modicationRequiresVoting then AddMenuItem(GetString(SI_GROUP_LIST_MENU_DISBAND_GROUP), function() ZO_Dialogs_ShowDialog("GROUP_DISBAND_DIALOG") end) end else if not modicationRequiresVoting then AddMenuItem(GetString(SI_GROUP_LIST_MENU_KICK_FROM_GROUP), function() GroupKick(data.unitTag) end) end end end --Cannot vote for yourself if modicationRequiresVoting and not data.isPlayer then AddMenuItem(GetString(SI_GROUP_LIST_MENU_VOTE_KICK_FROM_GROUP), function() BeginGroupElection(GROUP_ELECTION_TYPE_KICK_MEMBER, ZO_GROUP_ELECTION_DESCRIPTORS.NONE, data.unitTag) end) end end --Per design, promoting doesn't expressly fall under the mantle of "group modification" if self.playerIsLeader and not data.isPlayer and data.online then AddMenuItem(GetString(SI_GROUP_LIST_MENU_PROMOTE_TO_LEADER), function() GroupPromote(data.unitTag) end) end self:ShowMenu(control) end end end function ZO_GroupList_Keyboard:TooltipIfTruncatedLabel_OnMouseEnter(control) if control:WasTruncated() then InitializeTooltip(InformationTooltip, control, BOTTOM) SetTooltipText(InformationTooltip, control:GetText()) end self:EnterRow(control.row) end function ZO_GroupList_Keyboard:Status_OnMouseEnter(control) local data = ZO_ScrollList_GetData(control.row) if(data.leader) then InitializeTooltip(InformationTooltip, control, BOTTOM) SetTooltipText(InformationTooltip, GetString(SI_GROUP_LIST_PANEL_LEADER_TOOLTIP)) end self:EnterRow(control.row) end function ZO_GroupList_Keyboard:Role_OnMouseEnter(control) if(control.role) then InitializeTooltip(InformationTooltip, control, BOTTOM) SetTooltipText(InformationTooltip, GetString("SI_LFGROLE", control.role)) end self:EnterRow(control.row) end function ZO_GroupList_Keyboard:UpdateHeaders(active) local color = active and self.activeColor or self.inactiveColor for i = 1, #self.headers do local header = self.headers[i] header:SetColor(color:UnpackRGBA()) end end --ZO_GroupList_Base overrides local ROLE_SELECTION_TO_ICON = { [LFG_ROLE_TANK] = { [true] = "EsoUI/Art/LFG/LFG_tank_down.dds", [false] = "EsoUI/Art/LFG/LFG_tank_disabled.dds", }, [LFG_ROLE_HEAL] = { [true] = "EsoUI/Art/LFG/LFG_healer_down.dds", [false] = "EsoUI/Art/LFG/LFG_healer_disabled.dds", }, [LFG_ROLE_DPS] = { [true] = "EsoUI/Art/LFG/LFG_dps_down.dds", [false] = "EsoUI/Art/LFG/LFG_dps_disabled.dds", }, } function ZO_GroupList_Keyboard:SetupGroupEntry(control, data) ZO_SortFilterList.SetupRow(self, control, data) ZO_SocialList_SharedSocialSetup(control, data) local hidden = (data.index % 2) == 0 control.bg:SetHidden(hidden) data.control = control control.leaderIcon:SetHidden(not data.leader) control.characterNameLabel:SetText(zo_strformat(SI_GROUP_LIST_PANEL_CHARACTER_NAME, data.index, ZO_FormatUserFacingCharacterName(data.rawCharacterName))) control.roleDPS:SetTexture(ROLE_SELECTION_TO_ICON[LFG_ROLE_DPS][data.isDps]) control.roleHeal:SetTexture(ROLE_SELECTION_TO_ICON[LFG_ROLE_HEAL][data.isHeal]) control.roleTank:SetTexture(ROLE_SELECTION_TO_ICON[LFG_ROLE_TANK][data.isTank]) end --ZO_SortFilterList overrides function ZO_GroupList_Keyboard:BuildMasterList() --Actual master list is managed by GROUP_LIST_MANAGER, but we have some other things we want to update when appropriate self.playerIsLeader = IsUnitGroupLeader("player") self.groupSize = GetGroupSize() self.noGroupRow:SetHidden(self.groupSize > 0) self:UpdateHeaders(self.groupSize > 0) KEYBIND_STRIP:UpdateKeybindButtonGroup(self.keybindStripDescriptor) end function ZO_GroupList_Keyboard:FilterScrollList() -- No real filtering...just show everything in the master list local scrollData = ZO_ScrollList_GetDataList(self.list) ZO_ClearNumericallyIndexedTable(scrollData) for _, data in ipairs(GROUP_LIST_MANAGER:GetMasterList()) do table.insert(scrollData, ZO_ScrollList_CreateDataEntry(GROUP_DATA, data)) end end function ZO_GroupList_Keyboard:GetRowColors(data, mouseIsOver) return ZO_SocialList_GetRowColors(data, mouseIsOver) end function ZO_GroupList_Keyboard:RefreshData() if not self.control:IsHidden() then ZO_SortFilterList.RefreshData(self) end PREFERRED_ROLES:RefreshRadioButtonGroupEnabledState() end --Global XML --------------- function ZO_GroupListRow_OnMouseEnter(control) GROUP_LIST:Row_OnMouseEnter(control) end function ZO_GroupListRow_OnMouseExit(control) GROUP_LIST:Row_OnMouseExit(control) end function ZO_GroupListRowChild_OnMouseExit(control) ClearTooltip(InformationTooltip) GROUP_LIST:Row_OnMouseExit(control.row) end function ZO_GroupListRow_OnMouseUp(control, button, upInside) GROUP_LIST:GroupListRow_OnMouseUp(control, button, upInside) end function ZO_GroupListRowCharacterName_OnMouseEnter(control) ZO_SocialListKeyboard.CharacterName_OnMouseEnter(GROUP_LIST, control) end function ZO_GroupListRowCharacterName_OnMouseExit(control) ZO_SocialListKeyboard.CharacterName_OnMouseExit(GROUP_LIST, control) end function ZO_GroupListRowClass_OnMouseEnter(control) ZO_SocialListKeyboard.Class_OnMouseEnter(GROUP_LIST, control) end function ZO_GroupListRowClass_OnMouseExit(control) ZO_SocialListKeyboard.Class_OnMouseExit(GROUP_LIST, control) end function ZO_GroupListRowChampion_OnMouseEnter(control) ZO_SocialListKeyboard.Champion_OnMouseEnter(GROUP_LIST, control) end function ZO_GroupListRowChampion_OnMouseExit(control) ZO_SocialListKeyboard.Champion_OnMouseExit(GROUP_LIST, control) end function ZO_GroupListRowTooltipIfTruncatedLabel_OnMouseEnter(control) GROUP_LIST:TooltipIfTruncatedLabel_OnMouseEnter(control) end function ZO_GroupListRowStatus_OnMouseEnter(control) GROUP_LIST:Status_OnMouseEnter(control) end function ZO_GroupListRole_OnMouseEnter(control) GROUP_LIST:Role_OnMouseEnter(control) end function ZO_GroupList_OnInitialized(self) GROUP_LIST = ZO_GroupList_Keyboard:New(self) end