diff options
Diffstat (limited to 'src/Chelleport.hs')
| -rw-r--r-- | src/Chelleport.hs | 91 |
1 files changed, 72 insertions, 19 deletions
diff --git a/src/Chelleport.hs b/src/Chelleport.hs index 9511ff5..f34bf27 100644 --- a/src/Chelleport.hs +++ b/src/Chelleport.hs @@ -1,42 +1,95 @@ module Chelleport where -import Chelleport.AppShell (Action (AppAction, SysQuit), DrawContext, setupAppShell) -import Chelleport.Draw (renderText) +import Chelleport.AppShell (Action (AppAction, SysQuit), DrawContext (ctxWindow), setupAppShell) +import Chelleport.Draw (colorLightGray, colorWhite, renderText) +import Chelleport.KeySequence (eventToKeycode, generateKeyCells, isValidKey, nextChars, toKeyChar) +import Control.Monad (forM_, unless, void) +import Data.IORef (modifyIORef', newIORef, readIORef) +import Data.List (isPrefixOf) +import Data.Text (splitOn) import qualified Data.Text as Text import qualified SDL +import Unsafe.Coerce (unsafeCoerce) -newtype State = State - { stateCount :: Int +data State = State + { stateCells :: [[[Char]]], + stateKeySequence :: [Char] } -newtype AppAction = ActionUpdateCount Int +data AppAction = FilterSequence SDL.Keycode | SetupGrid open :: IO () open = setupAppShell initialState update eventToAction render -initialState :: State -initialState = State {stateCount = 0} +padded :: Int -> a -> [a] -> [a] +padded 0 _ ls = ls +padded n x ls + | length ls > n = ls + | otherwise = padded (n - 1) x (ls ++ [x]) + +initialState :: DrawContext -> IO State +initialState _ctx = do + let cells = generateKeyCells (rows, columns) hintKeys + pure $ State {stateCells = cells, stateKeySequence = []} + where + rows = 16 + columns = 16 + hintKeys = "ABCDEFGIMNOPRSTUVWXYZ" render :: State -> DrawContext -> IO () render state ctx = do - renderText ctx $ Text.pack $ "Hello" ++ show (stateCount state) + (SDL.V2 width height) <- SDL.get $ SDL.windowSize $ ctxWindow ctx + let rows = stateCells state + let wcell = width `div` unsafeCoerce (length $ head rows) + let hcell = height `div` unsafeCoerce (length rows) + + forM_ (zip [0 ..] rows) $ \(rowIndex, row) -> do + forM_ (zip [0 ..] row) $ \(colIndex, cell) -> do + let w = colIndex * wcell + let h = rowIndex * hcell + let keySequence = stateKeySequence state + let (matched, remaining) = + if keySequence `isPrefixOf` cell + then splitAt (length keySequence) cell + else ("", cell) + + widthRef <- newIORef 0 + unless (null matched) $ do + let pos = w + (textWidth, _h) <- renderText ctx (SDL.V2 pos h) colorLightGray $ Text.pack matched + modifyIORef' widthRef (const textWidth) + unless (null remaining) $ do + prevTextWidth <- readIORef widthRef + let pos = w + prevTextWidth + void $ renderText ctx (SDL.V2 pos h) colorWhite $ Text.pack remaining update :: State -> DrawContext -> AppAction -> IO State -update state _ctx (ActionUpdateCount count) = do - -- SDL.warpMouse SDL.WarpGlobal $ SDL.P $ SDL.V2 (unsafeCoerce $ 10 * stateCount state) 100 - pure state {stateCount = count} +update state _ctx SetupGrid = pure state +update state _ctx (FilterSequence key) = + case validChars >>= (\chars -> (,chars) <$> toKeyChar key) of + Just (keyChar, validChars') + | keyChar `elem` validChars' -> + pure state {stateKeySequence = stateKeySequence state ++ [keyChar]} + _ -> pure state + where + validChars = nextChars (stateKeySequence state) (stateCells state) eventToAction :: State -> SDL.Event -> Maybe (Action AppAction) -eventToAction state event = +eventToAction _state event = case SDL.eventPayload event of + -- SDL.WindowShownEvent _ -> Just $ AppAction SetupGrid + SDL.QuitEvent -> Just SysQuit SDL.KeyboardEvent ev - | isKeyPress ev SDL.KeycodeQ -> Just SysQuit - | isKeyPress ev SDL.KeycodeEscape -> Just SysQuit - | isKeyPress ev SDL.KeycodeJ -> Just $ AppAction $ ActionUpdateCount (stateCount state - 1) - | isKeyPress ev SDL.KeycodeK -> Just $ AppAction $ ActionUpdateCount (stateCount state + 1) + | isKeyPressWith ev SDL.KeycodeQ -> Just SysQuit + | isKeyPressWith ev SDL.KeycodeEscape -> Just SysQuit + | isKeyPress ev && isValidKey (eventToKeycode ev) -> + Just $ AppAction $ FilterSequence $ eventToKeycode ev _ -> Nothing -isKeyPress :: SDL.KeyboardEventData -> SDL.Keycode -> Bool -isKeyPress keyboardEvent keyCode = +isKeyPress :: SDL.KeyboardEventData -> Bool +isKeyPress keyboardEvent = SDL.keyboardEventKeyMotion keyboardEvent == SDL.Pressed - && SDL.keysymKeycode (SDL.keyboardEventKeysym keyboardEvent) == keyCode + +isKeyPressWith :: SDL.KeyboardEventData -> SDL.Keycode -> Bool +isKeyPressWith keyboardEvent keyCode = + isKeyPress keyboardEvent && SDL.keysymKeycode (SDL.keyboardEventKeysym keyboardEvent) == keyCode |
