aboutsummaryrefslogtreecommitdiff
path: root/src/Chelleport/View.hs
blob: cf51390505fad2d5a7ffd779ba6df4efab3596d5 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
module Chelleport.View (render) where

import Chelleport.Draw
import Chelleport.Types
import Control.Monad (forM_, unless, void)
import Data.IORef (modifyIORef', newIORef, readIORef)
import Data.List (isPrefixOf)
import qualified Data.Text as Text
import Foreign.C (CInt)
import SDL (($=))
import qualified SDL
import Unsafe.Coerce (unsafeCoerce)

isEmpty :: [a] -> Bool
isEmpty = null

render :: State -> DrawContext -> IO ()
render state ctx = do
  renderGridLines state ctx

  (SDL.V2 width height) <- SDL.get $ SDL.windowSize $ ctxWindow ctx
  let grid = stateCells state
  let wcell = width `div` unsafeCoerce (length $ head grid)
  let hcell = height `div` unsafeCoerce (length grid)

  forM_ (zip [0 ..] grid) $ \(rowIndex, row) -> do
    let py = rowIndex * hcell
    forM_ (zip [0 ..] row) $ \(colIndex, cell) -> do
      let px = colIndex * wcell
      renderKeySequence ctx (stateKeySequence state) cell (px, py)

renderKeySequence :: DrawContext -> KeySequence -> Cell -> (CInt, CInt) -> IO ()
renderKeySequence ctx keySequence cell (px, py) = do
  let (matched, remaining)
        | keySequence `isPrefixOf` cell = splitAt (length keySequence) cell
        | otherwise = ("", cell)

  let textColor
        | isEmpty keySequence = colorWhite
        | not $ isEmpty matched = colorAccent
        | otherwise = colorGray

  widthRef <- newIORef 0
  unless (isEmpty matched) $ do
    (textWidth, _h) <- drawText ctx (SDL.V2 px py) colorLightGray $ Text.pack matched
    modifyIORef' widthRef (const textWidth)

  unless (isEmpty remaining) $ do
    prevTextWidth <- readIORef widthRef
    let pos = px + prevTextWidth
    void $ drawText ctx (SDL.V2 pos py) textColor $ Text.pack remaining

renderGridLines :: State -> DrawContext -> IO ()
renderGridLines state ctx = do
  (SDL.V2 width height) <- SDL.get $ SDL.windowSize $ ctxWindow ctx
  let grid = stateCells state
  let wcell = width `div` unsafeCoerce (length $ head grid)
  let hcell = height `div` unsafeCoerce (length grid)

  SDL.rendererDrawColor (ctxRenderer ctx) $= colorGridLines
  let rows = unsafeCoerce $ length grid
  let columns = unsafeCoerce $ length $ head grid
  forM_ [0 .. rows] $ \rowIndex -> do
    drawHorizontalLine ctx $ rowIndex * hcell
  forM_ [0 .. columns] $ \colIndex -> do
    drawVerticalLine ctx $ colIndex * wcell

  SDL.rendererDrawColor (ctxRenderer ctx) $= colorAxisLines
  drawHorizontalLine ctx (rows * hcell `div` 2)
  drawVerticalLine ctx (columns * wcell `div` 2)