{-# LANGUAGE MultiParamTypeClasses #-} module Network.OnRmt.UI.BrickUI (brickUI) where import Brick.AttrMap import Brick.Main import Brick.Types import BrickCompat (BChan, newBChan, writeBChan, defaultConfig) import Concurrent.Worker ( WorkMsg, StateCmd(..), WorkMsg(..) , WorkItems(..), WorkState(..) , WorkId, DispBlk(..)) import Control.Monad.IO.Class (liftIO) import Data.Default (def) import qualified Data.Text as T import Graphics.Vty (Attr(..), Event(..), mkVty) import Graphics.Vty.Attributes (defAttr) import Network.OnRmt.UI (OnRmtUI(..), stateEventHandler) import Network.OnRmt.UI.MainScreen ( Screen(..), newScreen, drawScreen , handleScreenEvents, chooseScreenCursor , ScreenElementNames, ScreenEventResult(..) , screenDefaultAttrs , setScreenItemState , setScreenProgress , resetOutput, addScreenOutput, updateScreen , logWrite) import TextUI.ItemField type UIElementNames = ScreenElementNames data BrickConfig = BrickConfig { b_appName :: T.Text , b_userAttrs :: [(AttrName, Attr)] , b_eventChan :: BChan BrickUIEvent } instance OnRmtUI BrickConfig BrickState where startUI = startBrickUI setUIItems = setBrickItems newOutput = setBrickOutput addOutput = addBrickOutput setProgress = setBrickProgress addLogInfo = addBrickLog setItemState = setBrickItemState endInfo = return -- setBrickItems sets itemfield information from worker information setBrickItems s i f = let ff = itemfield $ b_scrn s nf = ItemFieldWidget (itemFieldName ff) $ newItemField ni (identFunc f) ni = map w2i i w2i (WorkGroup n i) = ItemGroup n $ w2i i w2i (WorkItems n) = Items n scrn' = (b_scrn s) { itemfield = nf } s' = s { b_scrn = scrn' } identFunc Nothing = Nothing identFunc (Just f') = Just $ identF f' identF f' i s = f' i (ist82wst8 s) ist82wst8 Free = NoWork ist82wst8 Good = WorkDone ist82wst8 Bad = WorkFailed ist82wst8 Marked = NoWork in return s' data BrickState = BrickState { b_cfg :: BrickConfig , b_scrn :: Screen , b_workerRequest :: WorkMsg -> IO () , b_queryResponses :: [T.Text] } instance Show BrickState where show = show . b_scrn brickUI :: T.Text -> [(AttrName, Attr)] -> IO (BrickConfig, StateCmd -> IO (), BrickState) brickUI appName attrs = do eventChan <- newBChan 100000 return ( BrickConfig { b_appName = appName , b_userAttrs = attrs , b_eventChan = eventChan } , writeBChan eventChan . BUIE_StateEvent , undefined) startBrickUI :: BrickConfig -> (WorkMsg -> IO ()) -> BrickState -> IO BrickState startBrickUI brickCfg workerReq _ = customMain vty (Just evchan) brickApp brickState where brickApp = App { appDraw = drawUI , appHandleEvent = handleOnRmtEvents , appStartEvent = return , appAttrMap = const $ applyAttrMappings (b_userAttrs brickCfg) $ applyAttrMappings screenDefaultAttrs $ applyAttrMappings itemDefaultAttrs $ attrMap defAttr [] , appChooseCursor = chooseUICursor } vty = mkVty defaultConfig evchan = b_eventChan brickCfg brickState = BrickState { b_cfg = brickCfg , b_scrn = newScreen (b_appName brickCfg) field , b_workerRequest = workerReq , b_queryResponses = [] } field = newItemField nodes $ Just showf showf = showNode nodes nodes = [] showNode a b c = T.pack "" -- $ shows "#" $ shows a $ shows " is " $ shows b "" -- drawUI :: (Ord n, Show n) => UIControls n -> [Widget n] drawUI = drawScreen . b_scrn chooseUICursor = chooseScreenCursor . b_scrn data BrickUIEvent = BUIE_StateEvent StateCmd handleOnRmtEvents :: BrickState -> BrickEvent ScreenElementNames BrickUIEvent -> EventM ScreenElementNames (Next BrickState) handleOnRmtEvents ui (VtyEvent ev) = let workop s o = liftIO (b_workerRequest ui o) >> updscrn s updscrn s = continue $ ui { b_scrn = s } workop' o = liftIO (b_workerRequest ui o) >> continue ui in do r <- handleScreenEvents (b_scrn ui) ev case r of Continue s -> updscrn s ResetAll s -> do liftIO $ b_workerRequest ui ClearAll continue $ ui { b_scrn = s , b_queryResponses = [] } RequestWork s i m -> workop s $ StartRun i m UpdateSelection s n -> workop s $ ShowSelInfo n Quit -> halt ui MoreParallel -> workop' IncrParallel LessParallel -> workop' DecrParallel EnteredResponseGen s -> workop s StartResponse ResponseGenAdd s t -> workop s $ AddToResponse t ResponseGenRecord -> workop' EndResponse ExitedResponseGen s -> workop s AbandonResponse handleOnRmtEvents ui (AppEvent (BUIE_StateEvent ev)) = do ui' <- liftIO $ stateEventHandler ui ev continue ui' handleOnRmtEvents ui _ = continue ui setBrickOutput, addBrickOutput :: BrickState -> DispBlk -> IO BrickState setBrickOutput ui o = do n <- addScreenOutput o $ resetOutput $ outRgn $ b_scrn ui return $ ui { b_scrn = (b_scrn ui) { outRgn = n } } addBrickOutput ui o = do n <- addScreenOutput o $ outRgn $ b_scrn ui return $ ui { b_scrn = (b_scrn ui) { outRgn = n } } setBrickProgress ui t c = do s <- updateScreen (b_scrn ui) (return . setScreenProgress t c) return $ ui { b_scrn = s } addBrickLog ui t = return $ ui { b_scrn = logWrite t (b_scrn ui) } setBrickItemState ui s i = return $ ui { b_scrn = setScreenItemState s i (b_scrn ui) }