2020-02-08 03:43:36 +03:00
|
|
|
{-# LANGUAGE CPP #-}
|
2017-12-27 03:29:05 +03:00
|
|
|
{-# LANGUAGE TemplateHaskell #-}
|
|
|
|
{-# LANGUAGE OverloadedStrings #-}
|
|
|
|
module Main where
|
|
|
|
|
|
|
|
import qualified Data.Text as T
|
2018-01-09 00:06:55 +03:00
|
|
|
import Lens.Micro ((^.))
|
2017-12-27 03:29:05 +03:00
|
|
|
import Lens.Micro.TH
|
2020-02-08 03:43:36 +03:00
|
|
|
#if !(MIN_VERSION_base(4,11,0))
|
2017-12-27 08:56:10 +03:00
|
|
|
import Data.Monoid ((<>))
|
2020-02-08 03:43:36 +03:00
|
|
|
#endif
|
2017-12-27 03:29:05 +03:00
|
|
|
|
2017-12-27 09:32:01 +03:00
|
|
|
import qualified Graphics.Vty as V
|
2017-12-27 03:40:55 +03:00
|
|
|
import Brick
|
2017-12-27 03:29:05 +03:00
|
|
|
import Brick.Forms
|
2017-12-28 03:32:13 +03:00
|
|
|
( Form
|
|
|
|
, newForm
|
|
|
|
, formState
|
|
|
|
, formFocus
|
2018-01-09 00:06:55 +03:00
|
|
|
, setFieldValid
|
2017-12-28 03:32:13 +03:00
|
|
|
, renderForm
|
|
|
|
, handleFormEvent
|
|
|
|
, invalidFields
|
|
|
|
, allFieldsValid
|
|
|
|
, focusedFormInputAttr
|
|
|
|
, invalidFormInputAttr
|
|
|
|
, checkboxField
|
|
|
|
, radioField
|
|
|
|
, editShowableField
|
|
|
|
, editTextField
|
|
|
|
, editPasswordField
|
|
|
|
, (@@=)
|
|
|
|
)
|
2017-12-27 03:40:55 +03:00
|
|
|
import Brick.Focus
|
2017-12-28 03:32:13 +03:00
|
|
|
( focusGetCurrent
|
|
|
|
, focusRingCursor
|
|
|
|
)
|
|
|
|
import qualified Brick.Widgets.Edit as E
|
|
|
|
import qualified Brick.Widgets.Border as B
|
|
|
|
import qualified Brick.Widgets.Center as C
|
2017-12-27 03:29:05 +03:00
|
|
|
|
2017-12-27 08:31:18 +03:00
|
|
|
data Name = NameField
|
|
|
|
| AgeField
|
|
|
|
| BikeField
|
|
|
|
| HandedField
|
|
|
|
| PasswordField
|
|
|
|
| LeftHandField
|
|
|
|
| RightHandField
|
|
|
|
| AmbiField
|
2017-12-27 22:37:26 +03:00
|
|
|
| AddressField
|
2017-12-27 03:29:05 +03:00
|
|
|
deriving (Eq, Ord, Show)
|
|
|
|
|
2017-12-27 08:31:18 +03:00
|
|
|
data Handedness = LeftHanded | RightHanded | Ambidextrous
|
|
|
|
deriving (Show, Eq)
|
|
|
|
|
2017-12-28 02:37:51 +03:00
|
|
|
data UserInfo =
|
|
|
|
UserInfo { _name :: T.Text
|
|
|
|
, _age :: Int
|
|
|
|
, _address :: T.Text
|
|
|
|
, _ridesBike :: Bool
|
|
|
|
, _handed :: Handedness
|
|
|
|
, _password :: T.Text
|
|
|
|
}
|
|
|
|
deriving (Show)
|
|
|
|
|
|
|
|
makeLenses ''UserInfo
|
|
|
|
|
2017-12-28 05:34:58 +03:00
|
|
|
-- This form is covered in the Brick User Guide; see the "Input Forms"
|
|
|
|
-- section.
|
2017-12-28 02:37:51 +03:00
|
|
|
mkForm :: UserInfo -> Form UserInfo e Name
|
2017-12-27 03:29:05 +03:00
|
|
|
mkForm =
|
2017-12-27 08:52:26 +03:00
|
|
|
let label s w = padBottom (Pad 1) $
|
|
|
|
(vLimit 1 $ hLimit 15 $ str s <+> fill ' ') <+> w
|
|
|
|
in newForm [ label "Name" @@=
|
2017-12-27 08:39:20 +03:00
|
|
|
editTextField name NameField (Just 1)
|
2017-12-27 22:37:26 +03:00
|
|
|
, label "Address" @@=
|
2017-12-28 04:57:49 +03:00
|
|
|
B.borderWithLabel (str "Mailing") @@=
|
2017-12-27 22:37:26 +03:00
|
|
|
editTextField address AddressField (Just 3)
|
2017-12-27 08:52:26 +03:00
|
|
|
, label "Age" @@=
|
2017-12-27 08:39:20 +03:00
|
|
|
editShowableField age AgeField
|
2017-12-27 08:52:26 +03:00
|
|
|
, label "Password" @@=
|
2017-12-27 08:39:20 +03:00
|
|
|
editPasswordField password PasswordField
|
2017-12-27 08:52:26 +03:00
|
|
|
, label "Dominant hand" @@=
|
2017-12-27 08:39:20 +03:00
|
|
|
radioField handed [ (LeftHanded, LeftHandField, "Left")
|
|
|
|
, (RightHanded, RightHandField, "Right")
|
|
|
|
, (Ambidextrous, AmbiField, "Both")
|
|
|
|
]
|
2017-12-27 09:07:41 +03:00
|
|
|
, label "" @@=
|
2017-12-27 10:21:15 +03:00
|
|
|
checkboxField ridesBike BikeField "Do you ride a bicycle?"
|
2017-12-27 08:39:20 +03:00
|
|
|
]
|
2017-12-27 03:29:05 +03:00
|
|
|
|
|
|
|
theMap :: AttrMap
|
2017-12-28 03:33:03 +03:00
|
|
|
theMap = attrMap V.defAttr
|
|
|
|
[ (E.editAttr, V.white `on` V.black)
|
|
|
|
, (E.editFocusedAttr, V.black `on` V.yellow)
|
|
|
|
, (invalidFormInputAttr, V.white `on` V.red)
|
|
|
|
, (focusedFormInputAttr, V.black `on` V.yellow)
|
2017-12-27 03:29:05 +03:00
|
|
|
]
|
|
|
|
|
2017-12-28 02:37:51 +03:00
|
|
|
draw :: Form UserInfo e Name -> [Widget Name]
|
2017-12-28 03:32:13 +03:00
|
|
|
draw f = [C.vCenter $ C.hCenter form <=> C.hCenter help]
|
2017-12-27 08:52:26 +03:00
|
|
|
where
|
2017-12-28 03:32:13 +03:00
|
|
|
form = B.border $ padTop (Pad 1) $ hLimit 50 $ renderForm f
|
|
|
|
help = padTop (Pad 1) $ B.borderWithLabel (str "Help") body
|
2017-12-27 08:56:10 +03:00
|
|
|
body = str $ "- Name is free-form text\n" <>
|
|
|
|
"- Age must be an integer (try entering an\n" <>
|
|
|
|
" invalid age!)\n" <>
|
|
|
|
"- Handedness selects from a list of options\n" <>
|
2017-12-27 10:03:03 +03:00
|
|
|
"- The last option is a checkbox\n" <>
|
|
|
|
"- Enter/Esc quit, mouse interacts with fields"
|
2017-12-27 08:52:26 +03:00
|
|
|
|
2017-12-28 02:37:51 +03:00
|
|
|
app :: App (Form UserInfo e Name) e Name
|
2017-12-27 03:29:05 +03:00
|
|
|
app =
|
2017-12-27 08:52:26 +03:00
|
|
|
App { appDraw = draw
|
2017-12-27 03:29:05 +03:00
|
|
|
, appHandleEvent = \s ev ->
|
|
|
|
case ev of
|
2017-12-28 03:33:03 +03:00
|
|
|
VtyEvent (V.EvResize {}) -> continue s
|
|
|
|
VtyEvent (V.EvKey V.KEsc []) -> halt s
|
2017-12-27 22:37:26 +03:00
|
|
|
-- Enter quits only when we aren't in the multi-line editor.
|
2017-12-28 03:33:03 +03:00
|
|
|
VtyEvent (V.EvKey V.KEnter [])
|
2017-12-27 22:37:26 +03:00
|
|
|
| focusGetCurrent (formFocus s) /= Just AddressField -> halt s
|
2018-01-09 00:06:55 +03:00
|
|
|
_ -> do
|
|
|
|
s' <- handleFormEvent ev s
|
|
|
|
|
|
|
|
-- Example of external validation:
|
|
|
|
-- Require age field to contain a value that is at least 18.
|
2018-01-10 03:27:08 +03:00
|
|
|
continue $ setFieldValid ((formState s')^.age >= 18) AgeField s'
|
2018-01-09 00:06:55 +03:00
|
|
|
|
2017-12-27 03:29:05 +03:00
|
|
|
, appChooseCursor = focusRingCursor formFocus
|
|
|
|
, appStartEvent = return
|
|
|
|
, appAttrMap = const theMap
|
|
|
|
}
|
|
|
|
|
|
|
|
main :: IO ()
|
|
|
|
main = do
|
2017-12-27 09:32:01 +03:00
|
|
|
let buildVty = do
|
|
|
|
v <- V.mkVty =<< V.standardIOConfig
|
|
|
|
V.setMode (V.outputIface v) V.Mouse True
|
|
|
|
return v
|
|
|
|
|
2017-12-28 02:37:51 +03:00
|
|
|
initialUserInfo = UserInfo { _name = ""
|
|
|
|
, _address = ""
|
|
|
|
, _age = 0
|
|
|
|
, _handed = RightHanded
|
|
|
|
, _ridesBike = False
|
|
|
|
, _password = ""
|
|
|
|
}
|
2018-01-10 03:27:08 +03:00
|
|
|
f = setFieldValid False AgeField $
|
|
|
|
mkForm initialUserInfo
|
2017-12-27 09:32:01 +03:00
|
|
|
|
2019-03-19 18:25:49 +03:00
|
|
|
initialVty <- buildVty
|
|
|
|
f' <- customMain initialVty buildVty Nothing app f
|
2017-12-27 08:58:07 +03:00
|
|
|
|
|
|
|
putStrLn "The starting form state was:"
|
2017-12-28 02:37:51 +03:00
|
|
|
print initialUserInfo
|
2017-12-27 08:58:07 +03:00
|
|
|
|
|
|
|
putStrLn "The final form state was:"
|
2017-12-28 03:26:04 +03:00
|
|
|
print $ formState f'
|
2017-12-27 09:04:51 +03:00
|
|
|
|
|
|
|
if allFieldsValid f'
|
|
|
|
then putStrLn "The final form inputs were valid."
|
|
|
|
else putStrLn $ "The final form had invalid inputs: " <> show (invalidFields f')
|