swarm-0.7.0.0: src/swarm-tui/Swarm/TUI/Model/Menu.hs
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE ViewPatterns #-}
-- |
-- SPDX-License-Identifier: BSD-3-Clause
--
-- Sum types that represent menu options,
-- modal dialogs, and buttons.
module Swarm.TUI.Model.Menu where
import Brick.Widgets.Dialog (Dialog)
import Brick.Widgets.List qualified as BL
import Control.Lens hiding (from, (<.>))
import Data.List.Extra (enumerate)
import Data.List.NonEmpty (NonEmpty (..))
import Data.Text (Text)
import Data.Vector qualified as V
import Swarm.Game.Achievement.Definitions
import Swarm.Game.Entity as E
import Swarm.Game.Ingredients
import Swarm.Game.Scenario.Status (ScenarioPath (..))
import Swarm.Game.ScenarioInfo (
ScenarioCollection,
ScenarioItem (..),
ScenarioWith,
scenarioCollectionToList,
)
import Swarm.Game.World.Gen (Seed)
import Swarm.TUI.Model.Name
------------------------------------------------------------
-- Menus and dialogs
------------------------------------------------------------
data ScenarioOutcome = WinModal | LoseModal
deriving (Show, Eq)
data MidScenarioModalType
= HelpModal
| RecipesModal
| CommandsModal
| MessagesModal
| StructuresModal
| EntityPaletteModal
| TerrainPaletteModal
| RobotsModal
| DescriptionModal Entity
| GoalModal
deriving (Show, Eq)
data EndScenarioModalType
= ScenarioFinishModal ScenarioOutcome
| QuitModal
| KeepPlayingModal
deriving (Show, Eq)
data ModalType
= MidScenarioModal MidScenarioModalType
| EndScenarioModal EndScenarioModalType
deriving (Show, Eq)
data ButtonAction
= Cancel
| KeepPlaying
| StartOver Seed (ScenarioWith ScenarioPath)
| QuitAction
| Next (NonEmpty (ScenarioWith ScenarioPath))
data Modal = Modal
{ _modalType :: ModalType
, _modalDialog :: Dialog ButtonAction Name
}
makeLenses ''Modal
data MainMenuEntry
= NewGame
| Tutorial
| Achievements
| Messages
| About
| Quit
deriving (Eq, Ord, Show, Read, Bounded, Enum)
data Menu
= -- | We started playing directly from command line, no menu to show
NoMenu
| MainMenu (BL.List Name MainMenuEntry)
| -- | Stack of scenario item lists. INVARIANT: the currently selected
-- menu item is ALWAYS the same as the scenario currently being played.
-- See https://github.com/swarm-game/swarm/issues/1064 and
-- https://github.com/swarm-game/swarm/pull/1065.
NewGameMenu (NonEmpty (BL.List Name (ScenarioItem ScenarioPath)))
| AchievementsMenu (BL.List Name CategorizedAchievement)
| MessagesMenu
| AboutMenu
mainMenu :: MainMenuEntry -> BL.List Name MainMenuEntry
mainMenu e = BL.list MenuList (V.fromList enumerate) 1 & BL.listMoveToElement e
makePrisms ''Menu
-- | Create a brick 'BL.List' of scenario items from a 'ScenarioCollection'.
mkScenarioList :: ScenarioCollection a -> BL.List Name (ScenarioItem a)
mkScenarioList =
flip (BL.list ScenarioList) 1
. V.fromList
. scenarioCollectionToList
------------------------------------------------------------
-- Inventory list entries
------------------------------------------------------------
-- | An entry in the inventory list displayed in the info panel. We
-- can either have an entity with a count in the robot's inventory,
-- an entity equipped on the robot, or a labelled separator. The
-- purpose of the separators is to show a clear distinction between
-- the robot's /inventory/ and its /equipped devices/.
data InventoryListEntry
= Separator Text
| InventoryEntry Count Entity
| EquippedEntry Entity
deriving (Eq)
makePrisms ''InventoryListEntry