clone

fifteen puzzle games for the terminal, with daily puzzles, weekly ladders and xp, built on bubble tea

chore/app-model-decomp
puzzletea / games / shikaku / mouse.go
mouse.go 1.9K
1package shikaku23import "github.com/FelineStateMachine/puzzletea/game"45// screenToGrid converts terminal screen coordinates to grid cell coordinates.6// Returns (col, row, ok) where ok is false if the click landed outside the grid.7func (m *Model) screenToGrid(screenX, screenY int) (col, row int, ok bool) {8 return m.screenToGridAt(screenX, screenY, false)9}1011func (m *Model) screenToGridDrag(screenX, screenY int) (col, row int, ok bool) {12 return m.screenToGridAt(screenX, screenY, true)13}1415func (m *Model) screenToGridAt(screenX, screenY int, includeSeparators bool) (col, row int, ok bool) {16 ox, oy := m.cachedGridOrigin()17 return game.DynamicGridScreenToCell(18 game.DynamicGridMetrics{19 Width: m.puzzle.Width,20 Height: m.puzzle.Height,21 CellWidth: cellWidth,22 },23 ox,24 oy,25 screenX,26 screenY,27 includeSeparators,28 )29}3031// cachedGridOrigin returns the screen position of the top-left corner of32// cell (0,0), using a cached value when available. The cache is invalidated33// on terminal resize and solve-state changes.34func (m *Model) cachedGridOrigin() (x, y int) {35 if m.originValid {36 return m.originX, m.originY37 }38 x, y = m.gridOrigin()39 m.originX, m.originY = x, y40 m.originValid = true41 return x, y42}4344// gridOrigin computes the screen position of the top-left corner of the45// first grid cell. Mouse coordinates are terminal-absolute, so we need to46// account for how the root model centers the game's View() output.47//48// The root view does:49//50// lipgloss.Place(termWidth, termHeight, Center, Center, gameView)51//52// So the centering offset is (termWidth - viewWidth) / 2 for X and53// (termHeight - viewHeight) / 2 for Y.54//55// Within the game view the layout is:56//57// title58// dynamic grid59// info60// status61func (m *Model) gridOrigin() (x, y int) {62 solved := m.puzzle.IsSolved()63 title := game.TitleBarView("Shikaku", m.modeTitle, solved)64 grid := gridView(*m, solved)65 return game.DynamicGridOrigin(m.termWidth, m.termHeight, m.View(), title, grid)66}