ZO_GRID_SCROLL_LIST_AUTOFILL = true ZO_GRID_SCROLL_LIST_DONT_AUTOFILL = false ZO_AbstractGridScrollList = ZO_InitializingCallbackObject:Subclass() function ZO_AbstractGridScrollList:Initialize(control, autofillRows, resizeToFitColumnMax, resizeToFitRowMax) self.control = control self.container = control:GetNamedChild("Container") self.list = self.container:GetNamedChild("List") self:AddResizeOnScreenResize() self.scrollbar = self.list:GetNamedChild("ScrollBar") self.currentHeaderName = nil -- Maintaining backwards compatability self.currentHeaderData = nil self.nextOperationId = 1 self.indentAmount = 0 self.headerPrePadding = 0 self.headerPostPadding = 0 self.templateOperationIds = {} self.autoFillRows = autofillRows or false self.resizeToFitColumnMax = resizeToFitColumnMax or 0 self.resizeToFitRowMax = resizeToFitRowMax or 0 local minWidth, minHeight, maxWidth, maxHeight = self.control:GetDimensionConstraints() self.minWidth = minWidth self.minHeight = minHeight self.maxWidth = maxWidth self.maxHeight = maxHeight self.controlsAddedSinceLastFill = 0 if self.resizeToFitColumnMax > 0 then self.numCellsPerRow = self.resizeToFitColumnMax self.list:SetWidth(self.maxWidth + self.scrollbar:GetWidth()) end if self.resizeToFitRowMax > 0 then self.list:SetHeight(self.maxHeight) end end function ZO_AbstractGridScrollList:AddResizeOnScreenResize() local function OnScreenResized() ZO_ScrollList_SetHeight(self.list, self.list:GetHeight()) self:CommitGridList() end self.list:RegisterForEvent(EVENT_SCREEN_RESIZED, OnScreenResized) end function ZO_AbstractGridScrollList:SetHeaderPrePadding(prePadding) self.headerPrePadding = prePadding end function ZO_AbstractGridScrollList:SetHeaderPostPadding(postPadding) self.headerPostPadding = postPadding end function ZO_AbstractGridScrollList:SetIndentAmount(indentAmount) self.indentAmount = indentAmount internalassert(self.nextOperationId == 1, "You have to call this function before adding templates or they won't get the indent amount") end function ZO_AbstractGridScrollList:SetYDistanceFromEdgeWhereSelectionCausesScroll(yDistanceFromEdgeWhereSelectionCausesScroll) ZO_ScrollList_SetYDistanceFromEdgeWhereSelectionCausesScroll(self.list, yDistanceFromEdgeWhereSelectionCausesScroll) end function ZO_AbstractGridScrollList:AddHeaderTemplate(templateName, height, setupFunc, onHideFunc, resetControlFunc, considerHeaderWidth) if self.templateOperationIds[templateName] == nil then local operationId = self.nextOperationId local SPACING_XY = 0 local NOT_SELECTABLE = false local WIDTH = nil ZO_ScrollList_AddControlOperation(self.list, operationId, templateName, WIDTH, height, resetControlFunc, setupFunc, onHideFunc, SPACING_XY, SPACING_XY, self.indentAmount, NOT_SELECTABLE) ZO_ScrollList_SetTypeCategoryHeader(self.list, operationId, true) ZO_ScrollList_SetConsiderHeaderWidth(self.list, operationId, considerHeaderWidth) self.nextOperationId = self.nextOperationId + 1 self.templateOperationIds[templateName] = operationId return operationId end return nil end function ZO_AbstractGridScrollList:AddEntryTemplate(templateName, width, height, setupFunc, onHideFunc, resetControlFunc, spacingX, spacingY, centerEntries, isSelectable) if self.templateOperationIds[templateName] == nil then local operationId = self.nextOperationId if isSelectable == nil then isSelectable = true end ZO_ScrollList_AddControlOperation(self.list, operationId, templateName, width, height, resetControlFunc, setupFunc, onHideFunc, spacingX, spacingY, self.indentAmount, isSelectable, centerEntries) self.nextOperationId = self.nextOperationId + 1 self.templateOperationIds[templateName] = operationId if self.autoFillRows then assert(type(width) == "number", "AutoFillRows is not supported with dynamic width entry templates.") local listWidth = self.list:GetWidth() local numCellsPerRow = zo_floor(listWidth / (width + spacingX)) if self.numCellsPerRow then assert(self.numCellsPerRow == numCellsPerRow, "AutoFillRows is only supported when the number of cells per row is consistent regardless of the entry templates used.") else self.numCellsPerRow = numCellsPerRow end end return operationId end return nil end function ZO_AbstractGridScrollList:SetEntryTemplateVisibilityFunction(templateName, visiblityFunction) local operationId = self.templateOperationIds[templateName] if operationId then ZO_ScrollList_SetVisibilityFunction(self.list, operationId, visiblityFunction) end end function ZO_AbstractGridScrollList:SetEntryTemplateEqualityFunction(templateName, equalityFunction) local operationId = self.templateOperationIds[templateName] if operationId then ZO_ScrollList_SetEqualityFunction(self.list, operationId, equalityFunction) end end function ZO_AbstractGridScrollList:SetAutoFillEntryTemplate(templateName) self.autoFillRowsOperationId = self.templateOperationIds[templateName] end function ZO_AbstractGridScrollList:AddEntry(data, templateName) local operationId = self.templateOperationIds[templateName] if operationId then local gridHeaderData = data.gridHeaderName or data.gridHeaderData if self.currentHeaderData ~= gridHeaderData then local scrollData = ZO_ScrollList_GetDataList(self.list) if self.currentHeaderData or #scrollData > 0 then -- we're starting a new section, so first make sure to fill out the last row of the previous section self:FillRowWithEmptyCells(self.currentHeaderData) ZO_ScrollList_AddOperation(self.list, ZO_SCROLL_LIST_OPERATION_LINE_BREAK, { lineBreakAmount = self.headerPrePadding }) end self.currentHeaderData = gridHeaderData self.currentHeaderName = gridHeaderData -- Maintaining backwards compatability if self.currentHeaderData and self.currentHeaderData ~= "" then local headerOperationId = self.templateOperationIds[data.gridHeaderTemplate] -- data is only being kept for theoretical addon compat. There's no reason to have the entry data in the header operation, and no one should use it. ZO_ScrollList_AddOperation(self.list, headerOperationId, { header = gridHeaderData, data = data}) if self.headerPostPadding > 0 then ZO_ScrollList_AddOperation(self.list, ZO_SCROLL_LIST_OPERATION_LINE_BREAK, { lineBreakAmount = self.headerPostPadding, indentX = self.indentAmount }) end end end ZO_ScrollList_AddOperation(self.list, operationId, data) self.controlsAddedSinceLastFill = self.controlsAddedSinceLastFill + 1 end end function ZO_AbstractGridScrollList:FillRowWithEmptyCells(gridHeaderData) if self.autoFillRows and self.autoFillRowsOperationId then local numMissingCells = self.numCellsPerRow - zo_mod(self.controlsAddedSinceLastFill, self.numCellsPerRow) if numMissingCells ~= self.numCellsPerRow then -- the row was full, don't need to add any empty cells for i = 1, numMissingCells do ZO_ScrollList_AddOperation(self.list, self.autoFillRowsOperationId, { gridHeaderData = gridHeaderData, isEmptyCell = true }) end end end self.controlsAddedSinceLastFill = 0 end function ZO_AbstractGridScrollList:CommitGridList() local scrollData = ZO_ScrollList_GetDataList(self.list) if #scrollData > 0 then -- only try to fill in a row if there exists a row to fill in self:FillRowWithEmptyCells(self.currentHeaderData) end if self.resizeToFitColumnMax ~= 0 then self.list:SetWidth(self.maxWidth) end if self.resizeToFitRowMax ~= 0 then self.list:SetHeight(self.maxHeight) end ZO_ScrollList_Commit(self.list) if self.resizeToFitColumnMax ~= 0 then self.list:SetWidth(self.list.maxDimensionX + self.scrollbar:GetWidth()) end if self.resizeToFitRowMax ~= 0 then self.list:SetHeight(zo_min(self.maxHeight, self.list.maxDimensionY)) end end function ZO_AbstractGridScrollList:RecalculateVisibleEntries() -- At present determining which entries are visible is done in the commit -- But use a different function signature so we don't do any other behavior that might come with a call to CommitGridList in the future. -- CommitGridList is generally understood to be used after you add/remove entries from the list ZO_ScrollList_Commit(self.list) end function ZO_AbstractGridScrollList:IsSelectionOfTemplateType(templateName) local operationId = self.templateOperationIds[templateName] if operationId then local selectedData = ZO_ScrollList_GetSelectedData(self.list) if selectedData.dataEntry.typeId == operationId then return true end end return false end function ZO_AbstractGridScrollList:RefreshGridList() ZO_ScrollList_RefreshVisible(self.list) end function ZO_AbstractGridScrollList:RefreshGridListEntryData(entryData, overrideSetupCallback) ZO_ScrollList_RefreshVisible(self.list, entryData, overrideSetupCallback) end function ZO_AbstractGridScrollList:ClearGridList(retainScrollPosition) ZO_ScrollList_Clear(self.list) self.currentHeaderName = nil -- Maintaining backwards compatability self.currentHeaderData = nil if not retainScrollPosition then ZO_Scroll_ResetToTop(self.list) end end function ZO_AbstractGridScrollList:HasEntries() local dataList = ZO_ScrollList_GetDataList(self.list) return #dataList > 0 end function ZO_AbstractGridScrollList:AtTopOfGrid() return ZO_ScrollList_AtTopOfList(self.list) end function ZO_AbstractGridScrollList:GetData() return ZO_ScrollList_GetDataList(self.list) end function ZO_AbstractGridScrollList:GetControlFromData(data) return ZO_ScrollList_GetDataControl(self.list, data) end function ZO_AbstractGridScrollList:ScrollDataToCenter(data, onScrollCompleteCallback, animateInstantly) local dataIndex = ZO_ScrollList_GetDataIndex(self.list, data.dataEntry) if internalassert(dataIndex ~= nil) then ZO_ScrollList_SelectData(self.list, data) ZO_ScrollList_ScrollDataToCenter(self.list, dataIndex, onScrollCompleteCallback, animateInstantly) end end function ZO_AbstractGridScrollList:SelectData(data) local dataIndex = ZO_ScrollList_GetDataIndex(self.list, data.dataEntry) if internalassert(dataIndex ~= nil) then ZO_ScrollList_SelectData(self.list, data) end end function ZO_AbstractGridScrollList:SetAutoSelectToMatchingDataEntry(dataEntry) ZO_ScrollList_SetAutoSelectToMatchingDataEntry(self.list, dataEntry) end function ZO_AbstractGridScrollList:GetScrollValue() return ZO_ScrollList_GetScrollValue(self.list) end -- Deprecated: See ScrollToRelativeValue. function ZO_AbstractGridScrollList:ScrollToValue(value, onScrollCompleteCallback, animateInstantly) self:ScrollToRelativeValue(value, onScrollCompleteCallback, animateInstantly) end -- Scrolls by a relative offset. function ZO_AbstractGridScrollList:ScrollToRelativeValue(value, onScrollCompleteCallback, animateInstantly) ZO_ScrollList_ScrollRelative(self.list, value, onScrollCompleteCallback, animateInstantly) end -- Scrolls to an absolute position. function ZO_AbstractGridScrollList:ScrollToAbsoluteValue(absoluteScrollValue, onScrollCompleteCallback, animateInstantly) local currentScrollValue = self:GetScrollValue() local scrollValueOffset = absoluteScrollValue - currentScrollValue self:ScrollToRelativeValue(scrollValueOffset, onScrollCompleteCallback, animateInstantly) end function ZO_AbstractGridScrollList:ResetToTop() ZO_Scroll_ResetToTop(self.list) end function ZO_AbstractGridScrollList:AddLineBreak(lineBreakAmount) ZO_ScrollList_AddOperation(self.list, ZO_SCROLL_LIST_OPERATION_LINE_BREAK, { lineBreakAmount = lineBreakAmount }) end ---------------------- -- Global functions -- ---------------------- function ZO_DefaultGridHeaderSetup(control, data, selected) control:SetText(data.header) end function ZO_DefaultGridEntrySetup(control, data, list) if not control.icon then control.icon = control:GetNamedChild("Icon") end local icon = control.icon if data.iconColor then icon:SetColor(data.iconColor:UnpackRGBA()) end if data.iconDesaturation then icon:SetDesaturation(data.iconDesaturation) end if data.textureSampleProcessingWeights then for type, weight in pairs(data.textureSampleProcessingWeights) do icon:SetTextureSampleProcessingWeight(type, weight) end end local iconFile = data.iconFile or data.icon or (data.GetIcon and data:GetIcon()) if iconFile then icon:SetTexture(iconFile) icon:SetHidden(false) else icon:SetHidden(true) end end do local g_gridEntryScaleAnimationProvider = ZO_ReversibleAnimationProvider:New("ZO_GridEntry_IconSelectedAnimation") function ZO_GridEntry_SetIconScaledUp(control, scaledUp, instant) if control.icon then if scaledUp then g_gridEntryScaleAnimationProvider:PlayForward(control.icon, instant) else g_gridEntryScaleAnimationProvider:PlayBackward(control.icon, instant) end end end function ZO_GridEntry_SetIconScaledUpInstantly(control, scaledUp) ZO_GridEntry_SetIconScaledUp(control, scaledUp, true) end end function ZO_AbstractGridScrollList:GetSelectedData() return ZO_ScrollList_GetSelectedData(self.list) end