live-sequencer-0.0.3: http/enable/HTTPServer/GUI.hs
module HTTPServer.GUI (
HTTPServer.run,
GuiUpdate,
Feedback,
update,
methods,
) where
import qualified Module
import Utility.WX ( cursor )
import qualified HTTPServer
import qualified Graphics.UI.WX as WX
import Graphics.UI.WX.Attributes ( Prop((:=)), set, get )
import Graphics.UI.WX.Classes ( text )
import qualified Control.Concurrent.Split.MVar as MVar
import qualified Control.Monad.Exception.Synchronous as Exc
import Control.Monad.Trans.Class ( lift )
import qualified Data.Map as M
data GuiUpdate =
GetModuleList { _moduleList :: MVar.In [ Module.Name ] }
| GetModuleContent {
_moduleName :: Module.Name,
_moduleContent :: MVar.In (Exc.Exceptional HTTPServer.Error String) }
| UpdateModuleContent {
_moduleName :: Module.Name,
_moduleEditableContent :: String,
_moduleNewContent :: MVar.In Feedback }
type Feedback = Exc.Exceptional HTTPServer.Error (Maybe String, String)
methods :: (GuiUpdate -> IO ()) -> HTTPServer.Methods
methods output =
HTTPServer.Methods {
HTTPServer.getModuleList = do
(modListIn,modListOut) <- MVar.new
output $ GetModuleList modListIn
MVar.take modListOut,
HTTPServer.getModuleContent = \name -> Exc.ExceptionalT $ do
(contentIn,contentOut) <- MVar.new
output $ GetModuleContent name contentIn
MVar.take contentOut,
HTTPServer.updateModuleContent = \name edited -> Exc.ExceptionalT $ do
(newContentIn,newContentOut) <- MVar.new
output $ UpdateModuleContent name edited newContentIn
MVar.take newContentOut
}
update ::
(MVar.In Feedback -> Module.Name -> String -> Int -> IO ()) ->
WX.StatusField ->
M.Map Module.Name (WX.TextCtrl ()) ->
GuiUpdate ->
IO ()
update input status editors req =
case req of
GetModuleList modList ->
MVar.put modList . M.keys $ editors
GetModuleContent name content ->
(MVar.put content =<<) $ Exc.runExceptionalT $ do
editor <- getModule editors name
lift $ set status [ text :=
Module.tellName name ++ " downloaded by web client" ]
lift $ get editor text
UpdateModuleContent name content contentMVar -> do
result <- Exc.runExceptionalT $ do
editor <-
case M.lookup name editors of
Nothing ->
Exc.throwT
(Module.tellName name ++ " no longer available.",
"")
Just pnl -> return pnl
lift $ set status [ text :=
Module.tellName name ++ " updated by web client" ]
pos <- lift $ get editor cursor
localContent <- lift $ get editor text
case HTTPServer.splitProtected localContent of
(protected, sepEditable) ->
case sepEditable of
Nothing ->
Exc.throwT
("Module does no longer contain a separation mark, " ++
"thus you cannot alter the content.",
protected)
Just (sep, _edit) -> do
let newContent = protected ++ sep ++ '\n' : content
lift $ set editor [ text := newContent, cursor := pos ]
return (newContent, pos)
case result of
Exc.Exception (e, protected) ->
MVar.put contentMVar $
Exc.Success (Just e,
protected ++ HTTPServer.separatorLine ++ '\n' : content)
Exc.Success (newContent, pos) ->
input contentMVar name newContent pos
getModule ::
(Monad m) =>
M.Map Module.Name a ->
Module.Name ->
Exc.ExceptionalT HTTPServer.Error m a
getModule pnls name =
Exc.ExceptionalT $ return $
Exc.fromMaybe
(HTTPServer.notFound $ Module.tellName name ++ " not found") $
M.lookup name pnls