Guidance for Structuring a UI / Gridview Class

I was wondering there are any examples of a UI / gridview class?
I looked through the gridview example included with the SDK and was able to make the menu, but I didn't see a way to create it as a class.

I am working on making a store menu UI and I want to reuse it for different stores, passing in lists of items, prices, text, etc.

I'm mainly confused on how / where to call drawCell(), drawSectionHeader(), drawInRect(), etc.

I am working with Lua in the SDK for windows

Here is a stripped down version, where I'm just drawing some text to a box
I just get the following error when I create an instance of this class: field 'baseObject' is not callable (a nil value)

--import libraries
import 'CoreLibs/ui/gridview.lua'
import 'CoreLibs/nineslice'
import "CoreLibs/object"

--misc
local pd = playdate
local gfx = pd.graphics

--creates the StoreMenu class
class("StoreMenu").extends(pd.ui.gridview)
function StoreMenu:init(headerText)
	self.headerText = headerText
	self.menuFont = gfx.font.new('font/Bitmore-Medieval')
	self.menuFont:setTracking(1)

    --create dialog box
    self:setCellSize(0, 10)
	self.backgroundImage = pd.graphics.nineSlice.new("images/shadowbox", 4, 4, 45, 45)
	self:setNumberOfRows(1)
	self:setCellPadding(0, 0, 8, 8)
	self:setContentInset(8, 8, 6, 10)
end

--draw menu cells
function StoreMenu:drawCell(section, row, column, selected, x, y, width, height)
	gfx.setFont(self.menuFont)
	gfx.drawTextInRect(self.headerText, x+6, y+6, width, height+2, nil, "...")
end

--draw menu
function StoreMenu:drawStoreMenu()
	gfx.setColor(gfx.kColorWhite)
	gfx.fillRect(220, 20, 160, 200)
	self:drawInRect(10, 10, 380, 60)
end

Do you need to call StoreMenu.super.init(self)?

https://sdk.play.date/inside-playdate/#_structuring_your_project

import "A"
class("B").extends(A)

function B:init()
    B.super.init(self) -- calls superclass initializer
    -- initialization code goes here
end

I did try that as well: StoreMenu.super.init(self)
I also tried super with the parameters for gridview.new(): StoreMenu.super.init(0, 10)

I get the same error both ways: field 'baseObject' is not callable (a nil value)

I'd say there is no need to extend the class; you could just use it as intended, and work with self.storeMenuGridView, right? any parameters / configuration could still be applied in StoreMenu:init. I don't think you will lose reusability that way

Yeah that is how I have it working now, but the part that confuses me is where / when I should be calling drawCell(). I guess I should be calling that on the instance rather than from within the class? Something like:

newStore = StoreMenu(headerText)
newStore:drawCell()

I'm just trying to self-contain as much of the ui as I can so it doesn't become a big spaghetti mess

Even when you call gridView:drawInRect and let gridView call drawCell, you won't have to give up reusability; unless your call is to write an optimized GridView implementation that is more intelligent about which cells to draw.

I'm not sure I understand your motivation

I just ran into the same issue, and ended up doing this:

local pd <const> = playdate
local gfx <const> = pd.graphics

class('ItemListView').extends()

function ItemListView:init(cellWidth, cellHeight, options)
  ItemListView.super.init(self)
  
  self.options = options
  
  self._gridView = playdate.ui.gridview.new(cellWidth, cellHeight)
  
  -- self.options = options
  self._gridView:setNumberOfRows(#options)
  self._gridView:setCellPadding(0, 0, 13, 10)
  self._gridView:setContentInset(24, 24, 13, 11)

  self.font = gfx.getSystemFont()
  
  local listViewSelf = self
  function self._gridView:drawCell(section, row, column, selected, x, y, width, height)
	  if selected then
		  gfx.setColor(gfx.kColorBlack)
		  gfx.fillRoundRect(x, y, width, 20, 4)
		  gfx.setImageDrawMode(gfx.kDrawModeFillWhite)
	  else
		  gfx.setImageDrawMode(gfx.kDrawModeCopy)
	  end
	  gfx.setFont(listViewSelf.font)
	  gfx.drawTextInRect(listViewSelf.options[row], x, y+6, width, height+2, nil, "...", kTextAlignment.center)
  end
end

function ItemListView:selectNextRow(wrapSelection, scrollToSelection, animate)
  self._gridView:selectNextRow(wrapSelection, scrollToSelection, animate)
end

function ItemListView:selectPreviousRow(wrapSelection, scrollToSelection, animate)
  self._gridView:selectPreviousRow(wrapSelection, scrollToSelection, animate)
end

function ItemListView:drawInRect(x, y, w, h)
  self._gridView:drawInRect(x, y, w, h)
end

-- Elsewhere:
local itemListView = ItemListView(40, 20, { 'one', 'two', 'three', 'four', 'five' })

I can't say I'm happy about it, but I haven't figured out a better way to encapsulate this.

2 Likes