{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE UnicodeSyntax #-}
{-# LANGUAGE UndecidableInstances #-}
module Data.Geometry.Ipe.Attributes where
import Control.Lens hiding (rmap, Const)
import Data.Geometry.Ipe.Value
import Data.Singletons
import Data.Singletons.TH
import Data.Text (Text)
import Data.Vinyl
import Data.Vinyl.TypeLevel
import Data.Vinyl.Functor
import GHC.Exts
import Text.Read (lexP, step, parens, prec, (+++)
, Lexeme(Ident), readPrec, readListPrec, readListPrecDefault)
data AttributeUniverse =
Layer | Matrix | Pin | Transformations
| Stroke | Fill | Pen | Size
| Dash | LineCap | LineJoin
| FillRule | Arrow | RArrow | Opacity | Tiling | Gradient
| Clip
deriving (Show,Read,Eq)
genSingletons [ ''AttributeUniverse ]
type CommonAttributes = [ Layer, Matrix, Pin, Transformations ]
type TextLabelAttributes = CommonAttributes
type MiniPageAttributes = CommonAttributes
type ImageAttributes = CommonAttributes
type SymbolAttributes = CommonAttributes ++
[Stroke, Fill, Pen, Size]
type PathAttributes = CommonAttributes ++
[ Stroke, Fill, Dash, Pen, LineCap, LineJoin
, FillRule, Arrow, RArrow, Opacity, Tiling, Gradient
]
type GroupAttributes = CommonAttributes ++ '[ 'Clip]
newtype Attr (f :: TyFun u * -> *)
(label :: u) = GAttr { _getAttr :: Maybe (Apply f label) }
deriving instance Eq (Apply f label) => Eq (Attr f label)
deriving instance Ord (Apply f label) => Ord (Attr f label)
makeLenses ''Attr
pattern Attr :: Apply f label -> Attr f label
pattern Attr x = GAttr (Just x)
pattern NoAttr :: Attr f label
pattern NoAttr = GAttr Nothing
{-# COMPLETE NoAttr, Attr #-}
instance Show (Apply f label) => Show (Attr f label) where
showsPrec d NoAttr = showParen (d > app_prec) $ showString "NoAttr"
where app_prec = 10
showsPrec d (Attr a) = showParen (d > up_prec) $
showString "Attr " . showsPrec (up_prec+1) a
where up_prec = 5
instance Read (Apply f label) => Read (Attr f label) where
readPrec = parens $ (prec app_prec $ do
Ident "NoAttr" <- lexP
pure NoAttr)
+++ (prec up_prec $ do
Ident "Attr" <- lexP
a <- step readPrec
pure $ Attr a)
where
app_prec = 10
up_prec = 5
readListPrec = readListPrecDefault
instance Semigroup (Attr f l) where
_ <> b@(Attr _) = b
a <> _ = a
instance Monoid (Attr f l) where
mempty = NoAttr
mappend = (<>)
newtype Attributes (f :: TyFun u * -> *) (ats :: [u]) = Attrs (Rec (Attr f) ats)
unAttrs :: Lens (Attributes f ats) (Attributes f' ats') (Rec (Attr f) ats) (Rec (Attr f') ats')
unAttrs = lens (\(Attrs r) -> r) (const Attrs)
deriving instance ( RMap ats, ReifyConstraint Show (Attr f) ats, RecordToList ats
, RecAll (Attr f) ats Show) => Show (Attributes f ats)
instance ( ReifyConstraint Eq (Attr f) ats, RecordToList ats
, RecAll (Attr f) ats Eq) => Eq (Attributes f ats) where
(Attrs a) == (Attrs b) = and . recordToList
. zipRecsWith (\x (Compose (Dict y)) -> Const $ x == y) a
. (reifyConstraint @Eq) $ b
instance RecApplicative ats => Monoid (Attributes f ats) where
mempty = Attrs $ rpure mempty
a `mappend` b = a <> b
instance Semigroup (Attributes f ats) where
(Attrs as) <> (Attrs bs) = Attrs $ zipRecsWith mappend as bs
zipRecsWith :: (forall a. f a -> g a -> h a)
-> Rec f as -> Rec g as -> Rec h as
zipRecsWith _ RNil _ = RNil
zipRecsWith f (r :& rs) (s :& ss) = f r s :& zipRecsWith f rs ss
attrLens :: forall at ats proxy f. (at ∈ ats)
=> proxy at -> Lens' (Attributes f ats) (Maybe (Apply f at))
attrLens _ = unAttrs.(rlens @at).getAttr
lookupAttr :: (at ∈ ats) => proxy at -> Attributes f ats -> Maybe (Apply f at)
lookupAttr p = view (attrLens p)
setAttr :: forall proxy at ats f. (at ∈ ats)
=> proxy at -> Apply f at -> Attributes f ats -> Attributes f ats
setAttr _ a (Attrs r) = Attrs $ rput (Attr a :: Attr f at) r
takeAttr :: forall proxy at ats f. (at ∈ ats)
=> proxy at -> Attributes f ats -> ( Maybe (Apply f at)
, Attributes f ats )
takeAttr p ats = (lookupAttr p ats, ats&attrLens p .~ Nothing)
unSetAttr :: forall proxy at ats f. (at ∈ ats)
=> proxy at -> Attributes f ats -> Attributes f ats
unSetAttr p = snd . takeAttr p
attr :: (at ∈ ats, RecApplicative ats)
=> proxy at -> Apply f at -> Attributes f ats
attr p x = setAttr p x mempty
data PinType = No | Yes | Horizontal | Vertical
deriving (Eq,Show,Read)
data TransformationTypes = Affine | Rigid | Translations deriving (Show,Read,Eq)
newtype IpeSize r = IpeSize (IpeValue r) deriving (Show,Eq,Ord)
newtype IpePen r = IpePen (IpeValue r) deriving (Show,Eq,Ord)
data IpeDash r = DashNamed Text
| DashPattern [r] r
deriving (Show,Eq)
data FillType = Wind | EOFill deriving (Show,Read,Eq)
type IpeOpacity = Text
type IpeTiling = Text
type IpeGradient = Text
data IpeArrow r = IpeArrow { _arrowName :: Text
, _arrowSize :: IpeSize r
} deriving (Show,Eq)
makeLenses ''IpeArrow
normalArrow :: IpeArrow r
normalArrow = IpeArrow "normal" (IpeSize $ Named "normal/normal")
class IpeAttrName (a :: AttributeUniverse) where
attrName :: proxy a -> Text
instance IpeAttrName Layer where attrName _ = "layer"
instance IpeAttrName Matrix where attrName _ = "matrix"
instance IpeAttrName Pin where attrName _ = "pin"
instance IpeAttrName Transformations where attrName _ = "transformations"
instance IpeAttrName Stroke where attrName _ = "stroke"
instance IpeAttrName Fill where attrName _ = "fill"
instance IpeAttrName Pen where attrName _ = "pen"
instance IpeAttrName Size where attrName _ = "size"
instance IpeAttrName Dash where attrName _ = "dash"
instance IpeAttrName LineCap where attrName _ = "cap"
instance IpeAttrName LineJoin where attrName _ = "join"
instance IpeAttrName FillRule where attrName _ = "fillrule"
instance IpeAttrName Arrow where attrName _ = "arrow"
instance IpeAttrName RArrow where attrName _ = "rarrow"
instance IpeAttrName Opacity where attrName _ = "opacity"
instance IpeAttrName Tiling where attrName _ = "tiling"
instance IpeAttrName Gradient where attrName _ = "gradient"
instance IpeAttrName Clip where attrName _ = "clip"
type family AllSatisfy (c :: k -> Constraint) (xs :: [k]) :: Constraint where
AllSatisfy c '[] = ()
AllSatisfy c (x ': xs) = (c x, AllSatisfy c xs)
writeAttrNames :: AllSatisfy IpeAttrName rs => Rec f rs -> Rec (Const Text) rs
writeAttrNames RNil = RNil
writeAttrNames (x :& xs) = Const (write'' x) :& writeAttrNames xs
where
write'' :: forall f s. IpeAttrName s => f s -> Text
write'' _ = attrName (Proxy :: Proxy s)