ige-0.1.0.0: src/IGE/Types.hs
module IGE.Types where
import Protolude
import Data.Complex
import Data.Graph.Inductive.Graph
import Data.Graph.Inductive.PatriciaTree
import Lens.Micro.Platform
import Control.Concurrent.STM
import Conduit
import Graphics.UI.Gtk (KeyVal)
import Graphics.Rendering.Cairo
import qualified Data.Map.Strict as Map
-- Refactoring ideas:
-- - Use typeclass-based EditorState
-- - Use StateT based Keybinding -- use hoisting to promote pure functions
-- -
type ℂ = Complex Double
class Translation a where
_x :: Lens' a Double
_y :: Lens' a Double
class Amplitwist a where
_r :: Lens' a Double
_θ :: Lens' a Double
instance Translation ℂ where
_x f (x :+ y) = (:+ y) <$> f x
_y f (x :+ y) = (x :+) <$> f x
instance Amplitwist ℂ where
_r f z = (* z) . (:+ 0) . (/ r) <$> f r
where r = magnitude z
_θ f z = (* z) . cis . (+ (-θ)) <$> f θ
where θ = phase z
class (Translation a, Amplitwist a) => RigidMotion a where
(^.^) :: a -> a -> a
(^*) :: a -> ℂ -> ℂ
-- law = (a ^.^ b) ^* z = a ^* (b ^* c)
data RM = RM { rmAT :: ℂ, rmTrans :: ℂ } -- rigid motion
deriving (Eq, Show)
makeLensesFor [("rmAT", "_at"), ("rmTrans", "_trans")] ''RM
instance Translation RM where
_x f (RM at trans) = (RM at) <$> _x f trans
_y f (RM at trans) = (RM at) <$> _y f trans
instance Amplitwist RM where
_r f (RM at trans) = (flip RM trans) <$> _r f at
_θ f (RM at trans) = (flip RM trans) <$> _θ f at
instance RigidMotion RM where
(RM at1 trans1) ^.^ (RM at2 trans2) = RM (at1 * at2) (trans1 + (at1 * trans2))
(RM at trans) ^* z = (z * at) + trans
class Renderable a where
render :: a -> ℂ -> Render ()
class Renderable a => RenderNode a where
renderNode :: a -> ℂ -> Render ()
renderNode = render
class Renderable a => RenderEdge a where
renderEdge :: a -> ℂ -> Render ()
renderEdge = render
data EditorState n e = EditorState {
esGraph :: Gr n e
, esRM :: RM
, esNum :: Int
, esCommand :: [Char] -- stored backwards
, esLabels :: [([Char], Node)]
, esNodeMap :: Map.Map Node ℂ
}
makeLensesFor [
("esGraph", "_graph")
, ("esRM", "_rm")
, ("esNum", "_num")
, ("esCommand", "_cmd")
, ("esLabels", "_labels")
, ("esNodeMap", "_nodeMap")] ''EditorState
newtype IGEM n e a = IGEM { unIGEM :: ReaderT (TVar (EditorState n e)) IO a }
deriving (Functor, Applicative, Monad, MonadIO, MonadReader (TVar (EditorState n e)))
runIGEM :: TVar (EditorState n e) -> IGEM n e a -> IO a
runIGEM v m = runReaderT (unIGEM m) v
type EditorM n e = State (EditorState n e)
runTVarState :: (MonadReader (TVar s) m, MonadIO m) => State s a -> m a
runTVarState action = do
stateVar <- ask
liftIO $ atomically $ do
s <- readTVar stateVar
let (a, s') = runState action s
writeTVar stateVar s'
return a
runTVarReader :: (MonadReader (TVar s) m, MonadIO m) => Reader s a -> m a
runTVarReader action = do
stateVar <- ask
s <- liftIO $ readTVarIO stateVar
return $ runReader action s
data RefreshType = LayoutChange | NoLayoutChange
deriving (Show, Eq)
type KeyBinding n e = ConduitM KeyVal RefreshType (IGEM n e)