Skip to content

Commit 7f0a544

Browse files
authored
Make robot grid simpler (#2443)
* Closes #2440
1 parent aa014c8 commit 7f0a544

File tree

8 files changed

+285
-447
lines changed

8 files changed

+285
-447
lines changed

src/swarm-tui/Swarm/TUI/Controller.hs

Lines changed: 28 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ import Brick.Widgets.Dialog
3434
import Brick.Widgets.Edit (Editor, applyEdit, editContentsL, handleEditorEvent)
3535
import Brick.Widgets.List (handleListEvent, listElements)
3636
import Brick.Widgets.List qualified as BL
37-
import Brick.Widgets.TabularList.Mixed
37+
import Brick.Widgets.TabularList.Grid qualified as BG
3838
import Control.Applicative ((<|>))
3939
import Control.Category ((>>>))
4040
import Control.Lens as Lens
@@ -108,7 +108,7 @@ import Swarm.TUI.Model.StateUpdate
108108
import Swarm.TUI.Model.UI
109109
import Swarm.TUI.Model.UI.Gameplay
110110
import Swarm.TUI.View.Popup (startPopupAnimation)
111-
import Swarm.TUI.View.Robot (getList)
111+
import Swarm.TUI.View.Robot
112112
import Swarm.TUI.View.Robot.Type
113113
import Swarm.Util hiding (both, (<<.=))
114114

@@ -296,8 +296,7 @@ handleNewGameMenuEvent scenarioStack@(curMenu :| rest) = \case
296296
invalidateCache
297297
let remaining = getScenariosAfterSelection curMenu pos
298298
startGame (siPair :| remaining) Nothing
299-
SICollection _ c -> do
300-
uiState . uiMenu .= NewGameMenu (NE.cons (mkScenarioList c) scenarioStack)
299+
SICollection _ c -> uiState . uiMenu .= NewGameMenu (NE.cons (mkScenarioList c) scenarioStack)
301300
CharKey 'o' -> showLaunchDialog
302301
CharKey 'O' -> showLaunchDialog
303302
Key V.KEsc -> exitNewGameMenu scenarioStack
@@ -318,7 +317,7 @@ handleNewGameMenuEvent scenarioStack@(curMenu :| rest) = \case
318317
exitNewGameMenu ::
319318
NonEmpty (BL.List Name (ScenarioItem ScenarioPath)) ->
320319
EventM Name AppState ()
321-
exitNewGameMenu stk = do
320+
exitNewGameMenu stk =
322321
uiState
323322
. uiMenu
324323
.= case snd (NE.uncons stk) of
@@ -445,7 +444,7 @@ closeModal m = do
445444
safeAutoUnpause
446445
uiGameplay . uiDialogs . uiModal .= Nothing
447446
-- message modal is not autopaused, so update notifications when leaving it
448-
when ((m ^. modalType) == MidScenarioModal MessagesModal) $ do
447+
when (m ^. modalType == MidScenarioModal MessagesModal) $ do
449448
t <- use $ gameState . temporal . ticks
450449
gameState . messageInfo . lastSeenMessageTime .= t
451450

@@ -458,11 +457,11 @@ handleModalEvent = \case
458457
Just (MidScenarioModal RobotsModal) -> do
459458
robotDialog <- use $ playState . scenarioState . uiGameplay . uiDialogs . uiRobot
460459
unless (robotDialog ^. isDetailsOpened) $ do
461-
let widget = robotDialog ^. robotListContent . robotsListWidget
462-
forM_ (BL.listSelectedElement $ getList widget) $ \x -> do
463-
Brick.zoom (playState . scenarioState . uiGameplay . uiDialogs . uiRobot) $ do
464-
isDetailsOpened .= True
465-
updateRobotDetailsPane $ snd x
460+
g <- use $ playState . scenarioState . gameState
461+
let widget = robotDialog ^. robotsGridList
462+
forM_ (getSelectedRobot g widget) $ \rob -> Brick.zoom (playState . scenarioState . uiGameplay . uiDialogs . uiRobot) $ do
463+
isDetailsOpened .= True
464+
Brick.zoom robotDetailsPaneState $ updateRobotDetailsPane rob
466465
_ -> do
467466
menu <- use $ uiState . uiMenu
468467

@@ -490,8 +489,7 @@ handleModalEvent = \case
490489
case modal of
491490
Just (MidScenarioModal TerrainPaletteModal) ->
492491
refreshList $ uiGameplay . uiWorldEditor . terrainList
493-
Just (MidScenarioModal EntityPaletteModal) -> do
494-
refreshList $ uiGameplay . uiWorldEditor . entityPaintList
492+
Just (MidScenarioModal EntityPaletteModal) -> refreshList $ uiGameplay . uiWorldEditor . entityPaintList
495493
Just (MidScenarioModal GoalModal) -> case ev of
496494
V.EvKey (V.KChar '\t') [] -> uiGameplay . uiDialogs . uiGoal . focus %= focusNext
497495
_ -> do
@@ -514,19 +512,20 @@ handleModalEvent = \case
514512
refreshList $ uiGameplay . uiDialogs . uiStructure . structurePanelListWidget
515513
StructureSummary -> handleInfoPanelEvent modalScroll (VtyEvent ev)
516514
_ -> handleInfoPanelEvent modalScroll (VtyEvent ev)
517-
Just (MidScenarioModal RobotsModal) -> Brick.zoom (uiGameplay . uiDialogs . uiRobot) $ case ev of
518-
V.EvKey (V.KChar '\t') [] -> robotDetailsFocus %= focusNext
519-
_ -> do
520-
isInDetailsMode <- use isDetailsOpened
521-
if isInDetailsMode
522-
then Brick.zoom (robotListContent . robotDetailsPaneState . logsList) $ handleListEvent ev
523-
else do
524-
Brick.zoom (robotListContent . robotsListWidget) $
525-
handleMixedListEvent ev
526-
527-
-- Ensure list widget content is updated immediately
528-
widget <- use $ robotListContent . robotsListWidget
529-
forM_ (BL.listSelectedElement $ getList widget) $ updateRobotDetailsPane . snd
515+
Just (MidScenarioModal RobotsModal) -> do
516+
uiGame <- use uiGameplay
517+
g <- use gameState
518+
Brick.zoom (uiGameplay . uiDialogs . uiRobot) $ case ev of
519+
V.EvKey (V.KChar '\t') [] -> robotDetailsPaneState . detailFocus %= focusNext
520+
_ -> do
521+
isInDetailsMode <- use isDetailsOpened
522+
if isInDetailsMode
523+
then Brick.zoom (robotDetailsPaneState . logsList) $ handleListEvent ev
524+
else do
525+
Brick.zoom robotsGridList $ BG.handleGridListEvent (robotGridRenderers uiGame g) ev
526+
-- Ensure list widget content is updated immediately
527+
mRob <- use $ robotsGridList . to (getSelectedRobot g)
528+
forM_ mRob $ Brick.zoom robotDetailsPaneState . updateRobotDetailsPane
530529
_ -> handleInfoPanelEvent modalScroll (VtyEvent ev)
531530
where
532531
refreshGoalList lw = nestEventM' lw $ handleListEventWithSeparators ev shouldSkipSelection
@@ -651,7 +650,7 @@ runBaseWebCode uinput ureply = do
651650
if s ^. gameState . gameControls . replWorking
652651
then liftIO . ureply $ Rejected AlreadyRunning
653652
else do
654-
gameState . gameControls . replListener .= (ureply . Complete . T.unpack)
653+
gameState . gameControls . replListener .= ureply . Complete . T.unpack
655654
runBaseCode uinput
656655
>>= liftIO . ureply . \case
657656
Left err -> Rejected . ParseError $ T.unpack err
@@ -847,9 +846,7 @@ tabComplete CompletionContext {..} names em theRepl = case theRepl ^. replPrompt
847846
FunctionName -> (possibleWords, isIdentChar)
848847

849848
possibleWords =
850-
names <> case ctxCreativeMode of
851-
True -> S.toList reservedWords
852-
False -> S.toList $ reservedWords `S.difference` creativeWords
849+
names <> (if ctxCreativeMode then S.toList reservedWords else S.toList $ reservedWords `S.difference` creativeWords)
853850

854851
entityNames = M.keys $ entitiesByName em
855852

@@ -904,7 +901,7 @@ adjReplHistIndex d s =
904901
newREPL :: REPLState
905902
newREPL = theRepl & replHistory %~ moveReplHistIndex d oldEntry
906903

907-
saveLastEntry = replLast .~ (theRepl ^. replPromptText)
904+
saveLastEntry = replLast .~ theRepl ^. replPromptText
908905
showNewEntry = (replPromptEditor .~ newREPLEditor newEntry) . (replPromptType .~ CmdPrompt [])
909906
-- get REPL data
910907
getCurrEntry = fromMaybe (theRepl ^. replLast) . getCurrentItemText . view replHistory

src/swarm-tui/Swarm/TUI/Controller/UpdateUI.hs

Lines changed: 14 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import Control.Lens as Lens
1919
import Control.Monad (forM_, unless, when)
2020
import Control.Monad.IO.Class (liftIO)
2121
import Data.Foldable (toList)
22-
import Data.Function (on)
2322
import Data.List.Extra (enumerate)
2423
import Data.Map.Strict qualified as M
2524
import Data.Maybe (isNothing)
@@ -53,7 +52,6 @@ import Swarm.TUI.Model.UI.Gameplay
5352
import Swarm.TUI.View.Objective qualified as GR
5453
import Swarm.TUI.View.Robot
5554
import Swarm.TUI.View.Robot.Type
56-
import Swarm.Util (applyJust)
5755
import Witch (into)
5856

5957
-- | Update the UI and redraw if needed.
@@ -191,8 +189,9 @@ updateUI = do
191189

192190
-- Update the robots modal only when it is enabled. See #2370.
193191
curModal <- use $ playState . scenarioState . uiGameplay . uiDialogs . uiModal
194-
when ((view modalType <$> curModal) == Just (MidScenarioModal RobotsModal)) $ do
195-
Brick.zoom (playState . scenarioState) $ doRobotListUpdate dOps g
192+
when ((view modalType <$> curModal) == Just (MidScenarioModal RobotsModal)) $
193+
Brick.zoom (playState . scenarioState . uiGameplay . uiDialogs . uiRobot) $
194+
doRobotListUpdate dOps g
196195

197196
let redraw =
198197
g ^. needsRedraw
@@ -203,36 +202,18 @@ updateUI = do
203202
|| newPopups
204203
pure redraw
205204

206-
doRobotListUpdate :: Set DebugOption -> GameState -> EventM Name ScenarioState ()
205+
doRobotListUpdate :: Set DebugOption -> GameState -> EventM Name RobotDisplay ()
207206
doRobotListUpdate dOps g = do
208-
gp <- use uiGameplay
209-
210-
let rd =
211-
mkRobotDisplay $
212-
RobotRenderingContext
213-
{ _mygs = g
214-
, _gameplay = gp
215-
, _timing = gp ^. uiTiming
216-
, _uiDbg = dOps
217-
}
218-
oldList = getList $ gp ^. uiDialogs . uiRobot . robotListContent . robotsListWidget
219-
maybeOldSelected = snd <$> BL.listSelectedElement oldList
220-
221-
-- Since we're replacing the entire contents of the list, we need to preserve the
222-
-- selected row here.
223-
maybeModificationFunc =
224-
updateList . BL.listFindBy . ((==) `on` view (robot . robotID)) <$> maybeOldSelected
225-
226-
uiGameplay . uiDialogs . uiRobot . robotListContent . robotsListWidget .= applyJust maybeModificationFunc rd
227-
228-
Brick.zoom (uiGameplay . uiDialogs . uiRobot) $
229-
forM_ maybeOldSelected updateRobotDetailsPane
230-
231-
updateRobotDetailsPane :: RobotWidgetRow -> EventM Name RobotDisplay ()
232-
updateRobotDetailsPane robotPayload =
233-
Brick.zoom robotListContent $ do
234-
robotDetailsPaneState . cmdHistogramList . BL.listElementsL .= V.fromList (M.toList (robotPayload ^. robot . activityCounts . commandsHistogram))
235-
robotDetailsPaneState . logsList . BL.listElementsL .= robotPayload ^. robot . robotLog
207+
robotsGridList %= updateRobotList dOps g
208+
rList <- use robotsGridList
209+
let mRob = getSelectedRobot g rList
210+
forM_ mRob $ \r -> do
211+
Brick.zoom robotDetailsPaneState $ updateRobotDetailsPane r
212+
213+
updateRobotDetailsPane :: Robot -> EventM Name RobotDetailsPaneState ()
214+
updateRobotDetailsPane rob = do
215+
cmdHistogramList . BL.listElementsL .= V.fromList (M.toList (rob ^. activityCounts . commandsHistogram))
216+
logsList . BL.listElementsL .= (rob ^. robotLog)
236217

237218
-- | Either pops up the updated Goals modal
238219
-- or pops up the Congratulations (Win) modal, or pops

src/swarm-tui/Swarm/TUI/Model/StateUpdate.hs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,6 @@ import Swarm.TUI.Model.UI.Gameplay
102102
import Swarm.TUI.View.Attribute.Attr (getWorldAttrName, swarmAttrMap)
103103
import Swarm.TUI.View.Attribute.CustomStyling (toAttrPair)
104104
import Swarm.TUI.View.Robot
105-
import Swarm.TUI.View.Robot.Type
106105
import Swarm.TUI.View.Structure qualified as SR
107106
import Swarm.Util
108107
import Swarm.Util.Effect (asExceptT, withThrow)
@@ -262,12 +261,7 @@ constructAppState (PersistentState rs ui key progState) opts@(AppOpts {..}) mCha
262261
{ _uiModal = Nothing
263262
, _uiGoal = emptyGoalDisplay
264263
, _uiStructure = emptyStructureDisplay
265-
, _uiRobot =
266-
RobotDisplay
267-
{ _robotDetailsFocus = focusRing $ map (RobotsListDialog . SingleRobotDetails) enumerate
268-
, _isDetailsOpened = False
269-
, _robotListContent = emptyRobotDisplay debugOptions
270-
}
264+
, _uiRobot = emptyRobotDisplay debugOptions
271265
}
272266
, _uiIsAutoPlay = False
273267
, _uiAutoShowObjectives = autoShowObjectives

src/swarm-tui/Swarm/TUI/View.hs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ module Swarm.TUI.View (
2020
-- * Robot panel
2121
drawRobotPanel,
2222
drawItem,
23-
renderDutyCycle,
2423

2524
-- * Info panel
2625
drawInfoPanel,
@@ -652,7 +651,7 @@ drawModal ::
652651
drawModal h ps isNoMenu = \case
653652
MidScenarioModal x -> case x of
654653
HelpModal -> helpWidget h $ gs ^. randomness . seed
655-
RobotsModal -> drawRobotsModal $ uig ^. uiDialogs . uiRobot
654+
RobotsModal -> drawRobotsDisplayModal uig gs $ uig ^. uiDialogs . uiRobot
656655
RecipesModal -> availableListWidget gs RecipeList
657656
CommandsModal -> commandsListWidget gs
658657
MessagesModal -> availableListWidget gs MessageList

0 commit comments

Comments
 (0)