{-# LANGUAGE TemplateHaskell #-} module Main where import Brick import Brick.Focus import Brick.Widgets.Border import Brick.Widgets.Center import Brick.Widgets.Edit import Brick.Widgets.DropDownMenu import Brick.Widgets.List (listAttr, listSelectedAttr) import Control.Category ((>>>)) import Data.Maybe (fromMaybe, mapMaybe) import Data.Text import Graphics.Vty (defAttr, blue, white, Event(EvKey), Key(..), Modifier(..)) import Lens.Micro import Lens.Micro.TH data Name = MenuBar | FileMenu | FileOpen | FileQuit | EditMenu | EditCut | HelpMenu | HelpAbout | Editor | About deriving (Eq, Ord, Show) data State = State { _menu :: DropDownMenu State Name , _edit :: Editor Text Name , _status :: String , _focus :: FocusRing Name } makeLenses ''State draw s = mconcat [ about $ focusGetCurrent (s^.focus) == Just About , [ withFocusRing (s^.focus) renderDropDownMenu (s^.menu) , translateBy (Location (0, 1)) $ vBox [ withFocusRing (s^.focus) (renderEditor (txt . Data.Text.unlines)) (s^.edit) , str $ s^.status, str " " ] ] ] about True = [centerLayer $ borderWithLabel (str "About this program") info] where info = padLeftRight 2 $ padTopBottom 1 $ str "This is a demo of the dropdownmenu widget." <=> str " " <=> showCursor About (Location (0, 0)) (str "Press ESC to continue") about _ = [] handleEvent :: State -> BrickEvent Name e -> EventM Name (Next State) handleEvent s (VtyEvent e) = fromMaybe accordingToFocus $ handleGlobalDropDownMenuEvent s menu (setFocus MenuBar) e where accordingToFocus = case focusGetCurrent $ s^.focus of Just MenuBar -> if e == EvKey KEsc [] && not (isDropDownMenuOpen (s^.menu)) then continue $ s & focus %~ focusSetCurrent Editor else handleDropDownMenuEvent s menu (setFocus MenuBar) e Just Editor -> case e of EvKey KEsc [] -> continue . setFocus MenuBar $ s _ -> continue =<< handleEventLensed s edit handleEditorEvent e Just About -> case e of EvKey KEsc [] -> continue . setFocus Editor $ s _ -> continue s Nothing -> continue s handleEvent s _ = continue s setFocus n = focus %~ focusSetCurrent n exitMenu x = menu %~ closeDropDownMenu >>> focus %~ focusSetCurrent x msg t = set status t >>> exitMenu Editor >>> continue aboutDialog = exitMenu About >>> continue menuD = [ ("File", FileMenu, Just (EvKey (KChar 'f') [MMeta]), [ ("Open", FileOpen, Just (EvKey (KChar 'o') [MCtrl]), msg "Not implemented") , ("Quit", FileQuit, Just (EvKey (KChar 'q') [MCtrl]), halt)]) , ("Edit", EditMenu, Just (EvKey (KChar 'e') [MMeta]), [("Cut", EditCut, Just (EvKey (KChar 'x') [MCtrl]), msg "This could cut something")]) , ("Help", HelpMenu, Just (EvKey (KChar 'h') [MMeta]), [("About this program", HelpAbout, Nothing, aboutDialog)]) ] demo = defaultMain App { appChooseCursor = showFirstCursor , appDraw = draw , appAttrMap = const attrs , appStartEvent = pure , appHandleEvent = handleEvent } main = demo State { _menu = dropDownMenu MenuBar menuD , _edit = editor Editor Nothing (pack "You can change this text.\nPress ESC to go to the menu.") , _status = "started." , _focus = focusRing [Editor, About, MenuBar] } attrs = attrMap defAttr [ (menuAttr, white `on` blue) , (menuSelectedAttr, blue `on` white) , (listAttr, white `on` blue) , (listSelectedAttr, blue `on` white) ]