-- | Checkbox control.
module NanoUI.Widgets.Checkbox (checkbox, checkbox') where

import Data.Text (Text)
import Effectful (Eff, type (:>))
import NanoUI.Context (adoptStoreInt, intKey, recordStoreInt, registerFocusable, writeStoreBool)
import NanoUI.Layout.Arena (NodeType (..))
import NanoUI.Monad (Ui, askContext, nextId, uiIO)
import NanoUI.Store (boolInt, intBool)
import NanoUI.Style (defaultLayout)
import NanoUI.Widgets.Behavior (keyActivated)
import NanoUI.Widgets.Node (Response, addWidget, respClicked, setChanged)

-- | Checkbox with a caption. Pass whether it is checked; the result is the
-- state after this frame's click or Space/Enter.
{-# INLINE checkbox #-}
checkbox :: Ui :> es => Text -> Bool -> Eff es Bool
checkbox :: forall (es :: [Effect]). (Ui :> es) => Text -> Bool -> Eff es Bool
checkbox Text
txt Bool
checked = (Response, Bool) -> Bool
forall a b. (a, b) -> b
snd ((Response, Bool) -> Bool)
-> Eff es (Response, Bool) -> Eff es Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Text -> Bool -> Eff es (Response, Bool)
forall (es :: [Effect]).
(Ui :> es) =>
Text -> Bool -> Eff es (Response, Bool)
checkbox' Text
txt Bool
checked

checkbox' :: Ui :> es => Text -> Bool -> Eff es (Response, Bool)
checkbox' :: forall (es :: [Effect]).
(Ui :> es) =>
Text -> Bool -> Eff es (Response, Bool)
checkbox' Text
txt Bool
checked = do
  wid <- Eff es WidgetId
forall (es :: [Effect]). (Ui :> es) => Eff es WidgetId
nextId
  ctx <- askContext
  uiIO $ registerFocusable ctx wid
  let key = WidgetId -> Int
intKey WidgetId
wid
  current <- intBool <$> uiIO (adoptStoreInt ctx wid key (boolInt checked))
  resp <- addWidget wid NodeCheckbox txt (if current then 1 else 0) defaultLayout
  keyClick <- keyActivated wid
  let
    clicked = Response -> Bool
forall r. HasResponse r => r -> Bool
respClicked Response
resp Bool -> Bool -> Bool
|| Bool
keyClick
    display = Bool
current Bool -> Bool -> Bool
forall a. Eq a => a -> a -> Bool
/= Bool
clicked
  uiIO $ do
    writeStoreBool ctx wid display
    recordStoreInt ctx key (boolInt display)
  pure (setChanged clicked resp, display)