aboutsummaryrefslogtreecommitdiff
path: root/src/Chelleport.hs
diff options
context:
space:
mode:
authorAkshay Nair <phenax5@gmail.com>2024-12-19 21:43:03 +0530
committerAkshay Nair <phenax5@gmail.com>2024-12-19 21:43:03 +0530
commitd44103add77718ae650bc0ad5e708e984192c29d (patch)
treec8b7e61e127c20032ca13ff52c2309e301aaa3f3 /src/Chelleport.hs
parentac5b4be69b2ba9d2ef17d31de11d1932f9566576 (diff)
downloadchelleport-d44103add77718ae650bc0ad5e708e984192c29d.tar.gz
chelleport-d44103add77718ae650bc0ad5e708e984192c29d.zip
Big refactoring
Diffstat (limited to 'src/Chelleport.hs')
-rw-r--r--src/Chelleport.hs120
1 files changed, 70 insertions, 50 deletions
diff --git a/src/Chelleport.hs b/src/Chelleport.hs
index 2bdc6c4..2a95a9a 100644
--- a/src/Chelleport.hs
+++ b/src/Chelleport.hs
@@ -1,22 +1,40 @@
+{-# LANGUAGE MultiParamTypeClasses #-}
+
module Chelleport where
-import Chelleport.AppShell (Action (AppAction, SysQuit), EventHandler, Update, hideWindow, setupAppShell)
-import Chelleport.Control (currentMousePosition, eventToKeycode, isKeyPress, isKeyPressWith, isKeyReleaseWith, moveMouse, triggerMouseLeftClick)
-import Chelleport.Draw (cellSize)
+import Chelleport.AppShell (MonadAppShell (hideWindow, shutdownApp), setupAppShell)
+import Chelleport.Context (initializeContext)
+import Chelleport.Control (MonadControl (getMousePointerPosition, moveMousePointer, pressMouseButton), directionalIncrement, eventToKeycode, isKeyPress, isKeyPressWith, isKeyReleaseWith)
+import Chelleport.Draw (MonadDraw, cellSize)
import Chelleport.KeySequence (findMatchPosition, generateGrid, isValidKey, nextChars, toKeyChar)
import Chelleport.Types
-import Chelleport.Utils (cIntToInt, intToCInt)
+import Chelleport.Utils (intToCInt)
import qualified Chelleport.View
+import Control.Monad.IO.Class (MonadIO)
+import Control.Monad.Reader (MonadReader, ReaderT (runReaderT))
import Data.List ((\\))
import Data.Maybe (fromMaybe, isJust)
-import Foreign.C (CInt)
import qualified SDL
-open :: IO ()
-open = setupAppShell initialState update eventToAction Chelleport.View.render
+runEff ::
+ (MonadIO m) =>
+ DrawContext ->
+ AppM m x ->
+ m x
+runEff ctx action = runReaderT (runAppM action) ctx
+
+run :: IO ()
+run = do
+ ctx <- initializeContext
+ setupAppShell
+ ctx
+ (runEff ctx initialState)
+ (\state -> runEff ctx . update state)
+ eventToAction
+ (runEff ctx . Chelleport.View.render)
-initialState :: DrawContext -> IO State
-initialState _ctx = do
+initialState :: (MonadIO m) => m State
+initialState = do
let cells = fromMaybe (pure undefined) $ generateGrid 0 (rows, columns) hintKeys
pure $
State
@@ -30,81 +48,83 @@ initialState _ctx = do
columns = 16
hintKeys = ['A' .. 'Z'] \\ "Q"
-directionalIncrement :: (CInt, CInt) -> Char -> (Int, Int)
-directionalIncrement (incx, incy) = \case
- 'H' -> (-cIntToInt incx, 0)
- 'L' -> (cIntToInt incx, 0)
- 'K' -> (0, -cIntToInt incy)
- 'J' -> (0, cIntToInt incy)
- _ -> undefined
+eventToAction :: EventHandler State AppAction
+eventToAction _state event =
+ case SDL.eventPayload event of
+ SDL.QuitEvent -> Just ShutdownApp
+ SDL.KeyboardEvent ev
+ | isKeyPressWith ev SDL.KeycodeQ -> Just ShutdownApp
+ | isKeyPressWith ev SDL.KeycodeEscape -> Just ShutdownApp
+ | isKeyPressWith ev SDL.KeycodeSpace -> Just TriggerLeftClick
+ | isKeyPressWith ev SDL.KeycodeTab -> Just ResetKeys
+ | isKeyPress ev && isValidKey (eventToKeycode ev) ->
+ Just $ HandleKeyInput $ eventToKeycode ev
+ | isKeyPressWith ev SDL.KeycodeLShift || isKeyPressWith ev SDL.KeycodeRShift ->
+ Just $ UpdateShiftState True
+ | isKeyReleaseWith ev SDL.KeycodeLShift || isKeyReleaseWith ev SDL.KeycodeRShift ->
+ Just $ UpdateShiftState False
+ _ -> Nothing
-update :: Update State AppAction
+update ::
+ (MonadIO m, MonadAppShell m, MonadDraw m, MonadControl m, MonadReader DrawContext m) =>
+ State ->
+ AppAction ->
+ m (State, Maybe AppAction)
-- Act on key inputs
-update state ctx (FilterSequence key) =
+update state (HandleKeyInput key) = do
case liftA2 (,) (toKeyChar key) validChars of
Just (keyChar, validChars')
| stateIsMatched state && keyChar `elem` ("HJKL" :: String) -> do
incr <- incrementValue
let action = IncrementMouseCursor $ directionalIncrement incr keyChar
- pure (state, Just . AppAction $ action)
+ pure (state, Just action)
| keyChar `elem` validChars' -> do
let newKeySequence = stateKeySequence state ++ [keyChar]
let matchPosition = findMatchPosition newKeySequence $ stateGrid state
let state' = state {stateKeySequence = newKeySequence, stateIsMatched = isJust matchPosition}
- pure (state', AppAction . MoveMousePosition <$> matchPosition)
+ pure (state', MoveMousePosition <$> matchPosition)
_ -> pure (state, Nothing)
where
validChars = nextChars (stateKeySequence state) (stateGrid state)
incrementValue = do
- (wcell, hcell) <- cellSize state ctx
+ (wcell, hcell) <- cellSize state
if stateIsShiftPressed state
then pure (wcell `div` 4, hcell `div` 4)
else pure (wcell `div` 16, hcell `div` 16)
-- Move mouse incrementally
-update state ctx (IncrementMouseCursor (incx, incy)) = do
- (SDL.V2 curx cury) <- currentMousePosition ctx
- moveMouse ctx (curx + intToCInt incx) (cury + intToCInt incy)
+update state (IncrementMouseCursor (incX, incY)) = do
+ (curX, curY) <- getMousePointerPosition
+ moveMousePointer (curX + intToCInt incX) (curY + intToCInt incY)
pure (state, Nothing)
-- Move mouse to given position
-update state ctx (MoveMousePosition (row, col)) = do
+update state (MoveMousePosition (row, col)) = do
(x, y) <- getPosition
- moveMouse ctx x y
+ moveMousePointer x y
pure (state, Nothing)
where
getPosition = do
- (wcell, hcell) <- cellSize state ctx
+ (wcell, hcell) <- cellSize state
let x = (wcell `div` 2) + wcell * intToCInt col
let y = (hcell `div` 2) + hcell * intToCInt row
pure (x, y)
-- Reset entered key sequence and state
-update state _ctx ResetKeys = do
+update state ResetKeys = do
pure (state {stateKeySequence = [], stateIsMatched = False}, Nothing)
-- Trigger left click
-update state ctx TriggerLeftClick = do
- hideWindow ctx
- triggerMouseLeftClick ctx
- pure (state, Just SysQuit)
+update state TriggerLeftClick = do
+ hideWindow
+ pressMouseButton LeftClick
+ pure (state, Just ShutdownApp)
--- Set/unset whether shift is pressed
-update state _ctx (UpdateShiftState shift) = pure (state {stateIsShiftPressed = shift}, Nothing)
+-- Cleanup everything and exit
+update state ShutdownApp = do
+ shutdownApp
+ pure (state, Nothing)
-eventToAction :: EventHandler State AppAction
-eventToAction _state event =
- case SDL.eventPayload event of
- SDL.QuitEvent -> Just SysQuit
- SDL.KeyboardEvent ev
- | isKeyPressWith ev SDL.KeycodeQ -> Just SysQuit
- | isKeyPressWith ev SDL.KeycodeEscape -> Just SysQuit
- | isKeyPressWith ev SDL.KeycodeSpace -> Just $ AppAction TriggerLeftClick
- | isKeyPressWith ev SDL.KeycodeTab -> Just $ AppAction ResetKeys
- | isKeyPress ev && isValidKey (eventToKeycode ev) ->
- Just . AppAction $ FilterSequence $ eventToKeycode ev
- | isKeyPressWith ev SDL.KeycodeLShift || isKeyPressWith ev SDL.KeycodeRShift ->
- Just . AppAction $ UpdateShiftState True
- | isKeyReleaseWith ev SDL.KeycodeLShift || isKeyReleaseWith ev SDL.KeycodeRShift ->
- Just . AppAction $ UpdateShiftState False
- _ -> Nothing
+-- Set/unset whether shift is pressed
+update state (UpdateShiftState shift) =
+ pure (state {stateIsShiftPressed = shift}, Nothing)