require("common.class") local ContainerField = require("api.page.containerfield") local ServiceField = require("api.page.servicefield") ---@class ListField: ContainerField, ServiceField ---@field selectedIndex integer ---@field locked boolean ---@field PADDING number[] local ListField = { __name = "ListField", MARGIN = {0, 0, 0, 0}, --{left, top, right, bottom} PADDING = {0, 0, 0, 0}, --{left, top, right, bottom} } ---Create a new ListField instance ---@param params? ListField # initial parameters ---@return ListField function ListField.new(params) params = params or {} --set instance members params.selectedIndex = params.selectedIndex or 1 params.locked = params.locked or false local self = CreateInstance(ListField, params, ContainerField, ServiceField) local minW = self.MARGIN[1] + self.PADDING[1] + self.PADDING[3] + self.MARGIN[3] local minH = self.MARGIN[2] + self.PADDING[2] + self.PADDING[4] + self.MARGIN[4] self.aabbW = math.max(self.aabbW, minW) self.aabbH = math.max(self.aabbH, minH) return self end ---@param obj? any # message object for the field function ListField:focus(obj) if self.focused then return end -- if obj message received about direction of cursor movement if obj and obj.direction then if obj.direction > 0 then self.selectedIndex = 1 elseif obj.direction < 0 then self.selectedIndex = #self.content end end -- else try to figure out by comparing current selected index if self.selectedIndex < 1 then self.selectedIndex = 1 elseif self.selectedIndex > #self.content then self.selectedIndex = #self.content end local field = self.content[self.selectedIndex] if field and field.focus then field:focus() end ServiceField.focus(self) end function ListField:unfocus() if not self.focused then return end local field = self.content[self.selectedIndex] if field and field.unfocus then field:unfocus() end ServiceField.unfocus(self) end ---Add field to list container ---@param field Field function ListField:addField(field) --update size self.aabbH = self.aabbH + field.aabbH local fieldAabbW = self.PADDING[1] + field.aabbW + self.PADDING[3] if self.aabbW < fieldAabbW then self.aabbW = fieldAabbW end --add field to container ContainerField.addField(self, field) end ---Refresh content parameters function ListField:refreshFields() local aabbH = self.MARGIN[2] + self.PADDING[2] + self.PADDING[4] + self.MARGIN[4] for _, child in ipairs(self.content) do --update size aabbH = aabbH + child.aabbH local fieldAabbW = self.PADDING[1] + child.aabbW + self.PADDING[3] if self.aabbW < fieldAabbW then self.aabbW = fieldAabbW end end self.aabbH = aabbH ContainerField.refreshFields(self) end ---@param button integer # options are under the `game` table prefixed with `BUTTON` ---@return boolean # true if further button input processing should be stopped, otherwise false function ListField:handleButtonInput(button) local field = self.content[self.selectedIndex] if field:handleButtonInput(button) then return true end if self.locked then return false end local direction = 0 if button == game.BUTTON_BTA then direction = -1 elseif button == game.BUTTON_BTB then direction = 1 end if direction ~= 0 then field:unfocus() self.selectedIndex = self.selectedIndex + direction if self.selectedIndex < 1 or self.selectedIndex > #self.content then return false end field = self.content[self.selectedIndex] field:focus() return true end return false end ---@param deltaTime number # frametime in seconds function ListField:drawContent(deltaTime) gfx.Translate(self.PADDING[1] + self.MARGIN[1], self.PADDING[2] + self.MARGIN[2]) for _, child in ipairs(self.content) do child:render(deltaTime) gfx.Translate(0, child.aabbH) end end return ListField