zwirn-0.2.3.1: app/zwirnmill/UI/Config.hs
{-# LANGUAGE FlexibleInstances #-}
{-# OPTIONS_GHC -Wno-orphans #-}
module UI.Config where
import Conferer (DefaultConfig (..))
import Conferer.FromConfig (FromConfig (..), fetchFromConfig, (/.))
import Data.List (mapAccumL)
import qualified Data.Map as Map
import Data.Maybe (fromMaybe, isJust)
import qualified Data.Text as T
import qualified Data.Vector as V
import Data.Yaml (ToJSON (..), object, (.=))
import Docs.Markdown (docMap, startDoc)
import Editor.Config (EditorConfig (..), editorFromConfig)
import Editor.Core (esFilePath, esTabWidth)
import Editor.Util (getContent)
import Lens.Micro ((^.))
import SampleBrowser.Load (loadSampleBrowser)
import UI.Core (AnimationConfig (..), Content (..), DocFocus (..), DocumentationConfig (..), EnvBrowser (..), Keyboard (..), Name (..), SampleBrowser (..), Window (..), WindowMap)
data WindowConfig = WindowConfig
{ windowConfigPosX :: Int,
windowConfigPosY :: Int,
windowConfigSizeX :: Int,
windowConfigSizeY :: Int,
windowConfigHidden :: Bool,
windowConfigBorder :: Bool,
windowConfigContent :: WindowContentConfig
}
deriving (Show)
data WindowContentConfig
= WindowAnimationConfig AnimationConfig
| WindowEditorConfig EditorConfig
| WindowOutputConfig
| WindowStatusConfig
| WindowSliderConfig
| WindowSampleBrowserConfig
| WindowEnvBrowserConfig
| WindowKeyboardConfig
| WindowDocumentationConfig DocumentationConfig
deriving (Show)
instance DefaultConfig [WindowConfig] where
configDef =
[ WindowConfig 0 0 51 28 False False (WindowEditorConfig $ EditorConfig 4 Nothing Nothing),
WindowConfig 51 0 23 11 False False WindowStatusConfig,
WindowConfig 51 11 23 17 False True WindowOutputConfig,
WindowConfig 74 00 29 28 False False (WindowDocumentationConfig (DocumentationConfig Nothing)),
WindowConfig 0 28 51 7 True True (WindowAnimationConfig $ AnimationConfig 150 "")
]
instance FromConfig WindowConfig where
fromConfig key configSource = do
pX <- fetchFromConfig (key /. "posx") configSource
pY <- fetchFromConfig (key /. "posy") configSource
sX <- fetchFromConfig (key /. "sizex") configSource
sY <- fetchFromConfig (key /. "sizey") configSource
b <- fetchFromConfig (key /. "border") configSource
h <- fetchFromConfig (key /. "hidden") configSource
wContent <- fetchFromConfig (key /. "content") configSource
return $
WindowConfig
{ windowConfigPosX = fromMaybe 0 pX,
windowConfigPosY = fromMaybe 0 pY,
windowConfigSizeX = fromMaybe 0 sX,
windowConfigSizeY = fromMaybe 0 sY,
windowConfigHidden = fromMaybe False h,
windowConfigBorder = fromMaybe True b,
windowConfigContent = wContent
}
instance FromConfig WindowContentConfig where
fromConfig key configSource = do
typ <- fetchFromConfig (key /. "type") configSource :: IO (Maybe String)
case typ of
Just "status" -> pure WindowStatusConfig
Just "output" -> pure WindowOutputConfig
Just "slider" -> pure WindowSliderConfig
Just "samplebrowser" -> pure WindowSampleBrowserConfig
Just "keyboard" -> pure WindowKeyboardConfig
Just "envbrowser" -> pure WindowEnvBrowserConfig
Just "animation" -> WindowAnimationConfig <$> fetchFromConfig key configSource
Just "editor" -> WindowEditorConfig <$> fetchFromConfig key configSource
Just "documentation" -> WindowDocumentationConfig <$> fetchFromConfig key configSource
_ -> pure WindowStatusConfig
instance FromConfig AnimationConfig where
fromConfig key configSource = do
r <- fetchFromConfig (key /. "rate") configSource
p <- fetchFromConfig (key /. "path") configSource
return (AnimationConfig (fromMaybe 150 r) (fromMaybe "" p))
instance FromConfig DocumentationConfig where
fromConfig key configSource = do
p <- fetchFromConfig (key /. "page") configSource
return (DocumentationConfig p)
windowFromConfig :: Maybe FilePath -> WindowConfig -> IO Window
windowFromConfig mf (WindowConfig x y sx sy hidden border conf) = do
cont <- contentFromType mf conf
return $ Window (x, y) (sx, sy) cont hidden border
contentFromType :: Maybe FilePath -> WindowContentConfig -> IO Content
contentFromType _ (WindowEditorConfig c) = do
es <- editorFromConfig c
return $ EditorContent es
contentFromType _ WindowStatusConfig = return $ StatusContent "" 138 0.575 0 0 (0, 32) 0 0 0
contentFromType _ WindowOutputConfig = return $ OutputContent []
contentFromType _ WindowSliderConfig = return $ SliderContent 0.5
contentFromType (Just p) WindowSampleBrowserConfig = loadSampleBrowser p >>= \sb -> return $ SampleBrowserContent sb
contentFromType _ WindowSampleBrowserConfig = return $ SampleBrowserContent (SampleB T.empty V.empty)
contentFromType _ WindowEnvBrowserConfig = return $ EnvBrowserContent (EnvB T.empty V.empty)
contentFromType _ WindowKeyboardConfig = return $ KeyboardContent (KeyB Nothing)
contentFromType _ (WindowDocumentationConfig (DocumentationConfig Nothing)) = return $ DocumentationContent startDoc NoFocus docMap
contentFromType _ (WindowDocumentationConfig (DocumentationConfig (Just k))) = case Map.lookup k docMap of
Just d -> return $ DocumentationContent d NoFocus docMap
Nothing -> return $ DocumentationContent startDoc NoFocus docMap
contentFromType _ (WindowAnimationConfig c) = return $ AnimationContent Nothing c
windowMapFromConfig :: Maybe FilePath -> [WindowConfig] -> IO WindowMap
windowMapFromConfig mf wcs = addHidden . Map.fromList <$> liftA2 zip ns ws
where
ws = mapM (windowFromConfig mf) wcs
ns = snd . mapAccumL (\st win -> windowNameFromContent st $ windowContent win) (0, 0) <$> ws
windowNameFromContent :: (Int, Int) -> Content -> ((Int, Int), Name)
windowNameFromContent (editors, sliders) (EditorContent _) = ((editors + 1, sliders), Editor $ editors + 1)
windowNameFromContent (editors, sliders) (SliderContent _) = ((editors, sliders + 1), Slider $ sliders + 1)
windowNameFromContent st (StatusContent {}) = (st, Status)
windowNameFromContent st (OutputContent {}) = (st, Output)
windowNameFromContent st (AnimationContent {}) = (st, Animator)
windowNameFromContent st (DocumentationContent {}) = (st, Documentation)
windowNameFromContent st (SampleBrowserContent {}) = (st, SampleBrowser)
windowNameFromContent st (EnvBrowserContent {}) = (st, EnvBrowser)
windowNameFromContent st (KeyboardContent {}) = (st, Keyboard)
addHidden :: WindowMap -> WindowMap
addHidden wm = insertKeyboard $ insertEnv $ insertSamples $ insertDoc $ insertStatus $ insertOutput $ insertAnimator wm
where
defaultWindow c = Window (0, 0) (10, 10) c True False
insertStatus = if Map.notMember Status wm then Map.insert Status (defaultWindow (StatusContent "" 138 0.575 0 0 (0, 32) 0 0 0)) else id
insertOutput = if Map.notMember Output wm then Map.insert Output (defaultWindow (OutputContent [])) else id
insertAnimator = if Map.notMember Animator wm then Map.insert Animator (defaultWindow (AnimationContent Nothing (AnimationConfig 150 ""))) else id
insertDoc = if Map.notMember Documentation wm then Map.insert Documentation (defaultWindow (DocumentationContent startDoc NoFocus docMap)) else id
insertSamples = if Map.notMember SampleBrowser wm then Map.insert SampleBrowser (defaultWindow (SampleBrowserContent (SampleB T.empty V.empty))) else id
insertEnv = if Map.notMember EnvBrowser wm then Map.insert EnvBrowser (defaultWindow (EnvBrowserContent (EnvB T.empty V.empty))) else id
insertKeyboard = if Map.notMember Keyboard wm then Map.insert Keyboard (defaultWindow (KeyboardContent (KeyB Nothing))) else id
configFromContent :: Content -> WindowContentConfig
configFromContent (EditorContent es) = WindowEditorConfig $ EditorConfig (es ^. esTabWidth) (es ^. esFilePath) (if isJust (es ^. esFilePath) then Nothing else Just $ getContent es)
configFromContent (StatusContent {}) = WindowStatusConfig
configFromContent (OutputContent _) = WindowOutputConfig
configFromContent (SliderContent _) = WindowSliderConfig
configFromContent (SampleBrowserContent _) = WindowSampleBrowserConfig
configFromContent (EnvBrowserContent _) = WindowEnvBrowserConfig
configFromContent (KeyboardContent _) = WindowKeyboardConfig
configFromContent (AnimationContent _ c) = WindowAnimationConfig c
configFromContent (DocumentationContent d _ m) = case Map.keys (Map.filter (== d) m) of
(x : _) -> WindowDocumentationConfig (DocumentationConfig (Just x))
_ -> WindowDocumentationConfig (DocumentationConfig Nothing)
configFromWindow :: Window -> WindowConfig
configFromWindow (Window (px, py) (sx, sy) c h b) = WindowConfig px py sx sy h b (configFromContent c)
configFromWindowMap :: WindowMap -> [WindowConfig]
configFromWindowMap = map configFromWindow . Map.elems
instance ToJSON WindowContentConfig where
toJSON WindowOutputConfig = object ["type" .= ("output" :: String)]
toJSON WindowStatusConfig = object ["type" .= ("status" :: String)]
toJSON WindowSliderConfig = object ["type" .= ("slider" :: String)]
toJSON WindowSampleBrowserConfig = object ["type" .= ("samplebrowser" :: String)]
toJSON WindowEnvBrowserConfig = object ["type" .= ("envbrowser" :: String)]
toJSON WindowKeyboardConfig = object ["type" .= ("keyboard" :: String)]
toJSON (WindowDocumentationConfig (DocumentationConfig k)) =
object
[ "type" .= ("documentation" :: String),
"page" .= k
]
toJSON (WindowAnimationConfig (AnimationConfig i p)) =
object
[ "type" .= ("animation" :: String),
"rate" .= i,
"path" .= p
]
toJSON (WindowEditorConfig (EditorConfig i p c)) =
object
[ "type" .= ("editor" :: String),
"tabwidth" .= i,
"path" .= p,
"content" .= c
]
instance ToJSON WindowConfig where
toJSON (WindowConfig px py sx sy h b c) =
object
[ "posx" .= px,
"posy" .= py,
"sizex" .= sx,
"sizey" .= sy,
"hidden" .= h,
"border" .= b,
"content" .= toJSON c
]