{-# OPTIONS -Wall #-} {-# LANGUAGE TemplateHaskell #-} module Main where import Control.Monad (when, unless) import Data.Maybe (fromJust, fromMaybe, isNothing) import Raylib.Core (clearBackground, closeWindow, initWindow, isKeyPressed, setTargetFPS, windowShouldClose) import Raylib.Types ( GuiControl (Statusbar), GuiControlProperty (TextPadding), GuiState (StateDisabled), GuiTextAlignmentVertical (TextAlignMiddle), KeyboardKey (KeyE, KeyU), Rectangle (Rectangle), Color, ) import Raylib.Util (WindowResources, drawing, raylibApplication) import Raylib.Util.GUI ( guiButton, guiDisable, guiEnable, guiGetState, guiGetStyleBackgroundColor, guiGroupBox, guiIsLocked, guiLabel, guiLabelButton, guiListView, guiLoadStyleDefault, guiLock, guiSetStyle, guiSetStyleTextAlignmentVertical, guiSetStyleTextSize, guiSpinner, guiStatusBar, guiTextBox, guiUnlock, guiWindowBox, guiCheckBox, guiColorPicker, ) import Raylib.Util.GUI.Styles ( guiLoadStyleAshes, guiLoadStyleBluish, guiLoadStyleCandy, guiLoadStyleCherry, guiLoadStyleCyber, guiLoadStyleDark, guiLoadStyleEnefete, guiLoadStyleJungle, guiLoadStyleLavanda, guiLoadStyleSunny, guiLoadStyleTerminal, ) data Page1 = Page1 { showWindowBox :: Bool, showForm :: Bool, firstName :: Maybe String, firstNameEditable :: Bool, lastName :: Maybe String, lastNameEditable :: Bool, age :: Maybe Int, ageEditable :: Bool } data Page2 = Page2 { scroll :: Int, theme :: Maybe Int, useCustomBackground :: Bool, customBackground :: Maybe Color } data AppState = AppState { window :: WindowResources, page :: Int, page1 :: Page1, page2 :: Page2 } defaultState :: WindowResources -> AppState defaultState w = AppState { window = w, page = 1, page1 = Page1 { showWindowBox = True, showForm = True, firstName = Nothing, firstNameEditable = False, lastName = Nothing, lastNameEditable = False, age = Nothing, ageEditable = False }, page2 = Page2 { theme = Nothing, scroll = 0, useCustomBackground = False, customBackground = Nothing } } width :: (Num a) => a width = 1000 height :: (Num a) => a height = 800 pages :: Int pages = 2 themes :: [IO ()] themes = [ guiLoadStyleDefault, guiLoadStyleAshes, guiLoadStyleBluish, guiLoadStyleCandy, guiLoadStyleCherry, guiLoadStyleCyber, guiLoadStyleDark, guiLoadStyleEnefete, guiLoadStyleJungle, guiLoadStyleLavanda, guiLoadStyleSunny, guiLoadStyleTerminal ] startup :: IO AppState startup = do w <- initWindow width height "raylib [raygui] test suite" setTargetFPS 60 guiSetStyleTextAlignmentVertical TextAlignMiddle guiSetStyle Statusbar TextPadding 20 return (defaultState w) mainLoop :: AppState -> IO AppState mainLoop state = do drawing ( do styleBackground <- guiGetStyleBackgroundColor clearBackground (if useCustomBackground (page2 state) then fromMaybe styleBackground (customBackground (page2 state)) else styleBackground) drawTitle drawLockAndDisableButtons state' <- drawPage (page state) newPage <- drawPaginationButtons (page state') return (state' {page = newPage}) ) where drawTitle = do guiState <- guiGetState guiSetStyleTextSize 40 guiLabel (Rectangle 20 20 (width - 40) 40) "raygui test suite" guiSetStyleTextSize 20 guiLabel (Rectangle 20 70 (width - 40) 20) ("gui state: " ++ show guiState) locked <- guiIsLocked let status | locked = "gui locked, press U to unlock GUI" | guiState == StateDisabled = "gui disabled, press E to enable GUI" | otherwise = "" guiStatusBar (Rectangle 0 (height - 40) width 40) status drawLockAndDisableButtons = do guiSetStyleTextSize 15 shouldDisable <- guiButton (Rectangle 20 (height - 90) 100 40) (Just "Disable GUI") shouldEnable <- isKeyPressed KeyE shouldLock <- guiButton (Rectangle 130 (height - 90) 100 40) (Just "Lock GUI") shouldUnlock <- isKeyPressed KeyU when shouldDisable guiDisable when shouldEnable guiEnable when shouldLock guiLock when shouldUnlock guiUnlock drawPaginationButtons p = do guiSetStyleTextSize 15 next <- guiButton (Rectangle (width - 120) (height - 90) 100 40) (Just "Next") previous <- guiButton (Rectangle (width - 230) (height - 90) 100 40) (Just "Previous") guiLabel (Rectangle (width - 330) (height - 90) 100 40) ("Page " ++ show p ++ " of " ++ show pages) let added = p + if next then 1 else if previous then (-1) else 0 return (if added < 1 || added > pages then p else added) drawPage 1 = drawFormPage drawPage 2 = drawThemePage drawPage _ = error "invalid page" drawFormPage = do let ps = page1 state containerMargin = 20 containerPadding = 20 containerSpacing = 20 containerY = 100 containerWidth = (width / 2) - containerMargin - (containerSpacing / 2) containerHeight = height - 200 formX = containerMargin infoX = containerWidth + containerMargin + containerSpacing guiGroupBox (Rectangle infoX containerY containerWidth containerHeight) (Just "user info") guiSetStyleTextSize 20 if isNothing (firstName ps) || isNothing (lastName ps) || isNothing (age ps) then guiLabel (Rectangle (infoX + containerPadding) (containerY + 30) 200 20) "Fill out the form" else do guiLabel (Rectangle (infoX + containerPadding) (containerY + 30) 200 20) ("First name: " ++ fromJust (firstName ps)) guiLabel (Rectangle (infoX + containerPadding) (containerY + 60) 200 20) ("Last name: " ++ fromJust (lastName ps)) guiLabel (Rectangle (infoX + containerPadding) (containerY + 90) 200 20) ("Age: " ++ show (fromJust (age ps))) if showWindowBox ps then ( do closeBox <- guiWindowBox (Rectangle formX containerY containerWidth containerHeight) (Just "form") guiSetStyleTextSize 20 if showForm ps then do hideForm <- guiLabelButton (Rectangle (formX + containerPadding) (containerY + 30) 100 20) (Just "Hide form") clearForm <- guiLabelButton (Rectangle (formX + containerPadding + 110) (containerY + 30) 100 20) (Just "Clear form") guiSetStyleTextSize 15 guiLabel (Rectangle (formX + containerPadding) (containerY + 65) 100 15) "First name" guiSetStyleTextSize 20 (firstNameToggled, firstName') <- guiTextBox (Rectangle (formX + containerPadding) (containerY + 85) (containerWidth - (2 * containerPadding)) 40) (fromMaybe "" (firstName ps)) Nothing (firstNameEditable ps) guiSetStyleTextSize 15 guiLabel (Rectangle (formX + containerPadding) (containerY + 135) 100 15) "Last name" guiSetStyleTextSize 20 (lastNameToggled, lastName') <- guiTextBox (Rectangle (formX + containerPadding) (containerY + 155) (containerWidth - (2 * containerPadding)) 40) (fromMaybe "" (lastName ps)) Nothing (lastNameEditable ps) guiSetStyleTextSize 15 guiLabel (Rectangle (formX + containerPadding) (containerY + 205) 100 15) "Age" guiSetStyleTextSize 20 (ageToggled, age') <- guiSpinner (Rectangle (formX + containerPadding) (containerY + 225) (containerWidth - (2 * containerPadding)) 40) Nothing (fromMaybe 0 (age ps)) 0 150 (ageEditable ps) return $ state { page1 = ps { showWindowBox = not closeBox, showForm = not hideForm, firstName = if clearForm || (firstName' == "") then Nothing else Just firstName', firstNameEditable = not clearForm && (if firstNameToggled then not (firstNameEditable ps) else firstNameEditable ps), lastName = if clearForm || (lastName' == "") then Nothing else Just lastName', lastNameEditable = not clearForm && (if lastNameToggled then not (lastNameEditable ps) else lastNameEditable ps), age = if clearForm then Nothing else Just age', ageEditable = not clearForm && (if ageToggled then not (ageEditable ps) else ageEditable ps) } } else do displayForm <- guiLabelButton (Rectangle (formX + containerPadding) 140 100 20) (Just "Show form") return $ state {page1 = ps {showWindowBox = not closeBox, showForm = displayForm}} ) else ( do guiSetStyleTextSize 20 createBox <- guiButton (Rectangle formX containerY containerWidth 40) (Just "Show window box") return $ state {page1 = ps {showWindowBox = createBox}} ) drawThemePage = do let ps = page2 state guiSetStyleTextSize 30 guiLabel (Rectangle 20 100 400 30) "Theme" guiSetStyleTextSize 20 (scroll', theme') <- guiListView (Rectangle 20 140 400 (height - 660)) "default;ashes;bluish;candy;cherry;cyber;dark;enefete;jungle;lavanda;sunny;terminal" (scroll ps) (theme ps) guiSetStyleTextSize 30 guiLabel (Rectangle 20 (height - 510) 360 30) "Custom background color" custom' <- guiCheckBox (Rectangle 390 (height - 510) 30 30) Nothing (useCustomBackground ps) oldState <- guiGetState unless custom' guiDisable color' <- guiColorPicker (Rectangle 20 (height - 470) 374 360) (customBackground ps) unless (oldState == StateDisabled) guiEnable when (theme' /= theme ps) (themes !! (fromMaybe 0 theme')) return $ state { page2 = ps { scroll = scroll', theme = theme', useCustomBackground = custom', customBackground = Just color' }} shouldClose :: AppState -> IO Bool shouldClose = const windowShouldClose teardown :: AppState -> IO () teardown s = closeWindow (window s) $(raylibApplication 'startup 'mainLoop 'shouldClose 'teardown)