Skip to content

Instantly share code, notes, and snippets.

@duplode
Forked from HeinrichApfelmus/InputElement.hs
Last active December 22, 2015 17:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save duplode/6506314 to your computer and use it in GitHub Desktop.
Save duplode/6506314 to your computer and use it in GitHub Desktop.
(Obsolete) variation of Apfelmus' example of a widget following the principles proposed in http://apfelmus.nfshost.com/blog/2012/03/29-frp-three-principles-bidirectional-gui.html .
{-# LANGUAGE RecordWildCards #-}
module InputElement where
import Data.Monoid
import Control.Monad
import qualified Graphics.UI.Threepenny as UI
import Graphics.UI.Threepenny
data Input = Input
{ iElement :: Element
, iUserValue :: Event String
, iValue :: Behavior String
}
newInput :: String -> Event String -> IO Input
newInput initialValue eValue = do
iElement <- UI.input # set UI.type_ "text"
let iUserValue = valueChange iElement
iValue <- initialValue `stepper` (unionWith const eValue iUserValue)
bEditing <- stepper False $ and <$>
unions [True <$ UI.domEvent "focus" iElement, False <$ UI.blur iElement]
onChange iValue $ \s -> do
editing <- currentValue bEditing
when (not editing) $ void $ element iElement # set value s
element iElement # set value initialValue
return $ Input {..}
module Main where
import Control.Monad (void)
import qualified Graphics.UI.Threepenny as UI
import Graphics.UI.Threepenny.Core
import InputElement
main :: IO ()
main = do
startGUI defaultConfig
{ tpPort = 10000
, tpCustomHTML = Nothing
, tpStatic = Just "."
} setup
setup :: Window -> IO ()
setup w = void $ do
btnBuenosAires <- UI.button # set UI.text "Buenos Aires"
btnLiverpool <- UI.button # set UI.text "Liverpool"
btnReset <- UI.button # set UI.text "Reset"
let defaultCity = "Tokyo"
eReset = defaultCity <$ UI.click btnReset
eBuenosAires = "Buenos Aires" <$ UI.click btnBuenosAires
eLiverpool = "Liverpool" <$ UI.click btnLiverpool
eSetCity = head <$> unions [ eReset, eBuenosAires, eLiverpool ]
iCity <- newInput defaultCity eSetCity
let bCity = iValue iCity
strLive <- string ""
element strLive # sink text bCity
btnUpdate1 <- UI.button # set text "Refresh city (1)"
btnUpdate2 <- UI.button # set text "Refresh city (2)"
let eUpdate1 = bCity <@ UI.click btnUpdate1
eUpdate2 = bCity <@ UI.click btnUpdate2
strOnDemand1 <- string defaultCity
strOnDemand2 <- string defaultCity
void $ register eUpdate1 $ \s -> void $ element strOnDemand1 # set text s
void $ register eUpdate2 $ \s -> void $ element strOnDemand2 # set text s
return w # set title "Input element demo"
getBody w #+
[ column
[ row [ string "Enter a city: "
, element $ iElement iCity, element btnReset ]
, row [ element btnBuenosAires, element btnLiverpool ]
, row [ string "Chosen city: "
, column [ element strLive
, row [ element strOnDemand1, element btnUpdate1 ]
, row [ element strOnDemand2, element btnUpdate2 ]
]
]
]
]
@duplode
Copy link
Author

duplode commented Sep 17, 2013

Note that this is not really a good design. See the discussions at the threepenny-gui issues page for better ideas.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment