packages feed

vty-ui-1.9: demos/PhoneInputDemo.hs

{-# LANGUAGE OverloadedStrings #-}
module Main where

-- This demo is discussed in the vty-ui user's manual.

import Control.Monad
import qualified Data.Text as T

import Graphics.Vty hiding (pad)
import Graphics.Vty.Widgets.All

data PhoneNumber = PhoneNumber T.Text T.Text T.Text
                   deriving (Show)

-- This type isn't pretty, but we have to specify the type of the
-- complete interface.  Initially you can let the compiler tell you
-- what it is.
type T = Box (Box
              (Box (Box (HFixed Edit) FormattedText) (HFixed Edit))
              FormattedText) (HFixed Edit)

data PhoneInput =
   PhoneInput { phoneInputWidget :: Widget T
              , edit1 :: Widget Edit
              , edit2 :: Widget Edit
              , edit3 :: Widget Edit
              , activateHandlers :: Handlers PhoneNumber
              }

newPhoneInput :: IO (PhoneInput, Widget FocusGroup)
newPhoneInput = do
   ahs <- newHandlers
   e1 <- editWidget
   e2 <- editWidget
   e3 <- editWidget
   ui <- (hFixed 4 e1) <++>
         (plainText "-") <++>
         (hFixed 4 e2) <++>
         (plainText "-") <++>
         (hFixed 5 e3)

   let w = PhoneInput ui e1 e2 e3 ahs
       doFireEvent = const $ do
         num <- mkPhoneNumber
         fireEvent w (return . activateHandlers) num

       mkPhoneNumber = do
         s1 <- getEditText e1
         s2 <- getEditText e2
         s3 <- getEditText e3
         return $ PhoneNumber s1 s2 s3

   e1 `onActivate` doFireEvent
   e2 `onActivate` doFireEvent
   e3 `onActivate` doFireEvent

   e1 `onChange` \s -> when (T.length s == 3) $ focus e2
   e2 `onChange` \s -> when (T.length s == 3) $ focus e3

   fg <- newFocusGroup
   mapM_ (addToFocusGroup fg) [e1, e2, e3]
   return (w, fg)

onPhoneInputActivate :: PhoneInput
                     -> (PhoneNumber -> IO ()) -> IO ()
onPhoneInputActivate input handler =
    addHandler (return . activateHandlers) input handler

main :: IO ()
main = do
  (p, fg) <- newPhoneInput
  p `onPhoneInputActivate` (error . show)

  ui <- padded (phoneInputWidget p) (padLeftRight 5 `pad` padTopBottom 2)

  c <- newCollection
  _ <- addToCollection c ui fg

  runUi c $ defaultContext { focusAttr = white `on` blue
                           }