Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

use nested sum type to simplify panel enumeration #876

Merged
merged 2 commits into from
Nov 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 20 additions & 16 deletions src/Swarm/TUI/Controller.hs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import Control.Carrier.State.Lazy qualified as Fused
import Control.Lens
import Control.Lens.Extras (is)
import Control.Monad.Except
import Control.Monad.Extra (whenJust)
import Control.Monad.State
import Data.Bits
import Data.Either (isRight)
Expand Down Expand Up @@ -292,34 +293,37 @@ handleMainEvent ev = do
| s ^. uiState . uiCheatMode -> gameState . creativeMode %= not
MouseDown n _ _ mouseLoc ->
case n of
WorldPanel -> do
FocusablePanel WorldPanel -> do
mouseCoordsM <- Brick.zoom gameState (mouseLocToWorldCoords mouseLoc)
uiState . uiWorldCursor .= mouseCoordsM
REPLInput -> do
setFocus REPLPanel
Copy link
Member Author

@kostmo kostmo Nov 22, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is moved to here.

handleREPLEvent ev
REPLInput -> handleREPLEvent ev
_ -> continueWithoutRedraw
MouseUp n _ _mouseLoc -> do
case n of
InventoryListItem pos -> uiState . uiInventory . traverse . _2 %= BL.listMoveTo pos
_ -> return ()
setFocus $ case n of
flip whenJust setFocus $ case n of
-- Adapt click event origin to their right panel.
-- For the REPL and the World view, using 'Brick.Widgets.Core.clickable' correctly set the origin.
-- However this does not seems to work for the robot and info panel.
-- Thus we force the destination focus here.
InventoryList -> RobotPanel
InventoryListItem _ -> RobotPanel
InfoViewport -> InfoPanel
_ -> n
kostmo marked this conversation as resolved.
Show resolved Hide resolved
InventoryList -> Just RobotPanel
InventoryListItem _ -> Just RobotPanel
InfoViewport -> Just InfoPanel
REPLInput -> Just REPLPanel
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved from here.

_ -> Nothing
case n of
FocusablePanel x -> setFocus x
_ -> return ()
-- dispatch any other events to the focused panel handler
_ev -> do
fring <- use $ uiState . uiFocusRing
case focusGetCurrent fring of
Just REPLPanel -> handleREPLEvent ev
Just WorldPanel -> handleWorldEvent ev
Just RobotPanel -> handleRobotPanelEvent ev
Just InfoPanel -> handleInfoPanelEvent infoScroll ev
Just (FocusablePanel x) -> ($ ev) $ case x of
REPLPanel -> handleREPLEvent
WorldPanel -> handleWorldEvent
RobotPanel -> handleRobotPanelEvent
InfoPanel -> handleInfoPanelEvent infoScroll
Comment on lines +322 to +326
Copy link
Member Author

@kostmo kostmo Nov 22, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's one more benefit of a dedicated sum type for Panels: we utilize exhuastiveness checking from the compiler here. The catch-all _ case no longer allows us to forget about a Panel; it instead handles all the non-panel Names.

_ -> continueWithoutRedraw

mouseLocToWorldCoords :: Brick.Location -> EventM Name GameState (Maybe W.Coords)
Expand All @@ -335,8 +339,8 @@ mouseLocToWorldCoords (Brick.Location mouseLoc) = do
my = fst mouseLoc' + snd regionStart
in pure . Just $ W.Coords (mx, my)

setFocus :: Name -> EventM Name AppState ()
setFocus name = uiState . uiFocusRing %= focusSetCurrent name
setFocus :: FocusablePanel -> EventM Name AppState ()
setFocus name = uiState . uiFocusRing %= focusSetCurrent (FocusablePanel name)

-- | Set the game to Running if it was (auto) paused otherwise to paused.
--
Expand Down Expand Up @@ -632,7 +636,7 @@ updateUI = do
-- them "sticky". They will be updated as soon as the player moves
-- the focus away.
fring <- use $ uiState . uiFocusRing
let sticky = focusGetCurrent fring `elem` [Just RobotPanel, Just InfoPanel]
let sticky = focusGetCurrent fring `elem` map (Just . FocusablePanel) [RobotPanel, InfoPanel]

-- Check if the robot log was updated and we are allowed to change
-- the inventory+info panels.
Expand Down
13 changes: 9 additions & 4 deletions src/Swarm/TUI/Model.hs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ module Swarm.TUI.Model (
-- * Custom UI label types
-- $uilabel
AppEvent (..),
FocusablePanel (..),
Name (..),

-- * Menus and dialogs
Expand Down Expand Up @@ -224,9 +225,7 @@ data AppEvent
| UpstreamVersion (Either NewReleaseFailure String)
deriving (Show)

-- | 'Name' represents names to uniquely identify various components
-- of the UI, such as forms, panels, caches, extents, and lists.
data Name
data FocusablePanel
= -- | The panel containing the REPL.
REPLPanel
| -- | The panel containing the world view.
Expand All @@ -235,6 +234,12 @@ data Name
RobotPanel
| -- | The info panel on the bottom left.
InfoPanel
deriving (Eq, Ord, Show, Read, Bounded, Enum)

-- | 'Name' represents names to uniquely identify various components
-- of the UI, such as forms, panels, caches, extents, and lists.
data Name
= FocusablePanel FocusablePanel
| -- | The REPL input form.
REPLInput
| -- | The render cache for the world view.
Expand Down Expand Up @@ -820,7 +825,7 @@ focusedEntity =

-- | The initial state of the focus ring.
initFocusRing :: FocusRing Name
initFocusRing = focusRing [REPLPanel, InfoPanel, RobotPanel, WorldPanel]
initFocusRing = focusRing $ map FocusablePanel listEnums

-- | The initial tick speed.
initLgTicksPerSecond :: Int
Expand Down
22 changes: 11 additions & 11 deletions src/Swarm/TUI/View.hs
Original file line number Diff line number Diff line change
Expand Up @@ -271,11 +271,11 @@ drawGameUI s =
hBox
[ hLimitPercent 25 $
vBox
[ vLimitPercent 50 $ panel highlightAttr fr RobotPanel plainBorder $ drawRobotPanel s
[ vLimitPercent 50 $ panel highlightAttr fr (FocusablePanel RobotPanel) plainBorder $ drawRobotPanel s
, panel
highlightAttr
fr
InfoPanel
(FocusablePanel InfoPanel)
( plainBorder
& topLabels . centerLabel
.~ (if moreTop then Just (txt " · · · ") else Nothing)
Expand All @@ -288,7 +288,7 @@ drawGameUI s =
[ panel
highlightAttr
fr
WorldPanel
(FocusablePanel WorldPanel)
( plainBorder
& bottomLabels . rightLabel ?~ padLeftRight 1 (drawTPS s)
& topLabels . leftLabel ?~ drawModalMenu s
Expand All @@ -297,11 +297,11 @@ drawGameUI s =
)
(drawWorld (s ^. uiState . uiShowRobots) (s ^. gameState))
, drawKeyMenu s
, clickable REPLPanel $
, clickable (FocusablePanel REPLPanel) $
panel
highlightAttr
fr
REPLPanel
(FocusablePanel REPLPanel)
( plainBorder
& topLabels . rightLabel .~ (drawType <$> (s ^. uiState . uiREPL . replType))
)
Expand Down Expand Up @@ -828,24 +828,24 @@ drawKeyMenu s =
"pop out" | (s ^. uiState . uiMoreInfoBot) || (s ^. uiState . uiMoreInfoTop) -> Alert
_ -> PanelSpecific

keyCmdsFor (Just REPLPanel) =
keyCmdsFor (Just (FocusablePanel REPLPanel)) =
[ ("↓↑", "history")
]
++ [("Enter", "execute") | not isReplWorking]
++ [("^c", "cancel") | isReplWorking]
++ [("M-p", renderControlModeSwitch ctrlMode) | creative]
keyCmdsFor (Just WorldPanel) =
keyCmdsFor (Just (FocusablePanel WorldPanel)) =
[ ("←↓↑→ / hjkl", "scroll") | creative
]
++ [("c", "recenter") | not viewingBase]
++ [("f", "FPS")]
keyCmdsFor (Just RobotPanel) =
keyCmdsFor (Just (FocusablePanel RobotPanel)) =
[ ("Enter", "pop out")
, ("m", "make")
, ("0", (if showZero then "hide" else "show") <> " 0")
, (":/;", T.unwords ["Sort:", renderSortMethod inventorySort])
]
keyCmdsFor (Just InfoPanel) = []
keyCmdsFor (Just (FocusablePanel InfoPanel)) = []
keyCmdsFor _ = []

data KeyHighlight = NoHighlight | Alert | PanelSpecific
Expand Down Expand Up @@ -874,7 +874,7 @@ drawWorld showRobots g =
. cached WorldCache
. reportExtent WorldExtent
-- Set the clickable request after the extent to play nice with the cache
. clickable WorldPanel
. clickable (FocusablePanel WorldPanel)
. Widget Fixed Fixed
$ do
ctx <- getContext
Expand Down Expand Up @@ -1217,7 +1217,7 @@ renderREPLPrompt focus repl = ps1 <+> replE
replE =
renderEditor
(color . vBox . map txt)
(focusGetCurrent focus `elem` [Nothing, Just REPLPanel, Just REPLInput])
(focusGetCurrent focus `elem` [Nothing, Just (FocusablePanel REPLPanel), Just REPLInput])
replEditor

-- | Draw the REPL.
Expand Down