Generalize the number type in SepcialQDiagram

This commit is contained in:
Robbie Gleichman 2016-12-02 19:43:03 -08:00
parent 59cd6757fe
commit 0f9c4d5b80
4 changed files with 109 additions and 110 deletions

View File

@ -31,18 +31,18 @@ import Data.Typeable(Typeable)
--import Diagrams.TwoD.Text(Text)
--import Data.Maybe(fromMaybe)
import Types(Icon(..), SpecialQDiagram, SpecialBackend)
import Types(Icon(..), SpecialQDiagram, SpecialBackend, SpecialNum)
import DrawingColors(colorScheme, ColorStyle(..))
-- TYPES --
type TransformableDia b = (Name -> Bool -> Double -> SpecialQDiagram b)
type TransformableDia b n = Name -> Bool -> Angle n -> SpecialQDiagram b n
-- COLORS --
lineCol :: Colour Double
lineCol = lineC colorScheme
-- FUNCTIONS --
iconToDiagram :: SpecialBackend b => Icon -> TransformableDia b
iconToDiagram :: SpecialBackend b n => Icon -> TransformableDia b n
iconToDiagram (ApplyAIcon n) = identDiaFunc $ applyADia n
iconToDiagram (PAppIcon n str) = pAppDia n str
iconToDiagram ResultIcon = identDiaFunc resultIcon
@ -114,16 +114,16 @@ portAngles icon port maybeName = case icon of
-- Warning: the first argument to nameDiagram can be almost any type,
-- so be careful with the parameter order.
identDiaFunc :: SpecialQDiagram b -> TransformableDia b
identDiaFunc :: SpecialNum n => SpecialQDiagram b n -> TransformableDia b n
identDiaFunc dia name _ _ = nameDiagram name dia
-- | Names the diagram and puts all sub-names in the namespace of the top level name.
nameDiagram :: IsName nm => nm -> SpecialQDiagram b -> SpecialQDiagram b
nameDiagram :: (IsName nm, SpecialNum n) => nm -> SpecialQDiagram b n -> SpecialQDiagram b n
nameDiagram name dia = named name (name .>> dia)
-- | Make an port with an integer name. Always use <> to add a ports (not === or |||)
--- since mempty has no size and will not be placed where you want it.
makePort :: Int -> SpecialQDiagram b
makePort :: SpecialNum n => Int -> SpecialQDiagram b n
makePort x = named x mempty
--makePort x = circle 0.2 # fc green # named x
-- Note, the version of makePort below seems to have a different type.
@ -137,13 +137,10 @@ defaultLineWidth = 0.15
circleRadius :: (Fractional a) => a
circleRadius = 0.5
apply0Triangle ::
(Typeable (N b), Transformable b, HasStyle b, TrailLike b,
V b ~ V2) =>
b
apply0Triangle :: SpecialBackend b n => SpecialQDiagram b n
apply0Triangle = lw none $ rotateBy (-1/12) $ eqTriangle (2 * circleRadius)
portCircle :: (SpecialBackend b) => SpecialQDiagram b
portCircle :: SpecialBackend b n => SpecialQDiagram b n
portCircle = lw none $ fc lineCol $ circle (circleRadius * 0.5)
-- applyA Icon--
@ -152,8 +149,8 @@ portCircle = lw none $ fc lineCol $ circle (circleRadius * 0.5)
-- Port 1: Result
-- Ports 2,3..: Arguments
coloredApplyADia ::
(SpecialBackend b) =>
Colour Double -> Int -> SpecialQDiagram b
(SpecialBackend b n) =>
Colour Double -> Int -> SpecialQDiagram b n
coloredApplyADia appColor n = centerXY finalDia where
trianglePortsCircle = hcat [
reflectX (fc appColor apply0Triangle),
@ -165,46 +162,46 @@ coloredApplyADia appColor n = centerXY finalDia where
topAndBottomLine = alignL $ lwG defaultLineWidth $ lc appColor $ hrule topAndBottomLineWidth
finalDia = topAndBottomLine === allPorts === topAndBottomLine
applyADia :: SpecialBackend b => Int -> SpecialQDiagram b
applyADia :: SpecialBackend b n => Int -> SpecialQDiagram b n
applyADia = coloredApplyADia (apply0C colorScheme)
textApplyADia :: SpecialBackend b =>
Int -> String -> TransformableDia b
textApplyADia :: SpecialBackend b n =>
Int -> String -> TransformableDia b n
textApplyADia = generalTextAppDia (textBoxTextC colorScheme) (apply0C colorScheme)
pAppDia :: SpecialBackend b =>
Int -> String -> TransformableDia b
pAppDia :: SpecialBackend b n =>
Int -> String -> TransformableDia b n
pAppDia = generalTextAppDia (patternTextC colorScheme) (patternC colorScheme)
--Get the decimal part of a float
reduceAngleRange :: Double -> Double
reduceAngleRange :: SpecialNum a => a -> a
reduceAngleRange x = x - fromInteger (floor x)
generalTextAppDia :: SpecialBackend b =>
Colour Double -> Colour Double -> Int -> String -> TransformableDia b
generalTextAppDia :: SpecialBackend b n =>
Colour Double -> Colour Double -> Int -> String -> TransformableDia b n
generalTextAppDia textCol borderCol numArgs str name reflect angle = nameDiagram name rotateDia where
rotateDia = transformCorrectedTextBox str textCol borderCol reflect angle |||
coloredApplyADia borderCol numArgs
transformCorrectedTextBox :: SpecialBackend b =>
String -> Colour Double -> Colour Double -> Bool -> Double -> SpecialQDiagram b
transformCorrectedTextBox :: SpecialBackend b n =>
String -> Colour Double -> Colour Double -> Bool -> Angle n -> SpecialQDiagram b n
transformCorrectedTextBox str textCol borderCol reflect angle =
rotateBy textBoxRotation (reflectIfTrue reflect (coloredTextBox textCol (opaque borderCol) str))
where
reducedAngle = reduceAngleRange angle
reducedAngle = reduceAngleRange (angle ^. turn)
textBoxRotation = if (reducedAngle > (1/4)) && (reducedAngle < (3/4)) then 1 / 2 else 0
reflectIfTrue shouldReflect dia = if shouldReflect then reflectX dia else dia
nestedApplyDia :: SpecialBackend b =>
[Maybe (Name, Icon)] -> TransformableDia b
nestedApplyDia :: SpecialBackend b n =>
[Maybe (Name, Icon)] -> TransformableDia b n
nestedApplyDia = generalNestedDia (apply0C colorScheme)
nestedPAppDia :: SpecialBackend b =>
[Maybe (Name, Icon)] -> TransformableDia b
nestedPAppDia :: SpecialBackend b n =>
[Maybe (Name, Icon)] -> TransformableDia b n
nestedPAppDia = generalNestedDia (patternC colorScheme)
generalNestedDia :: SpecialBackend b =>
Colour Double -> [Maybe (Name, Icon)] -> TransformableDia b
generalNestedDia :: SpecialBackend b n =>
Colour Double -> [Maybe (Name, Icon)] -> TransformableDia b n
generalNestedDia borderCol funcNameAndArgs name reflect angle = named name $ case funcNameAndArgs of
[] -> mempty
(maybeFunText:args) -> centerXY $ transformedText ||| centerY finalDia
@ -237,18 +234,17 @@ monoLetterWidthToHeightFraction = 0.61
textBoxHeightFactor :: (Fractional a) => a
textBoxHeightFactor = 1.1
textBox :: SpecialBackend b =>
String -> TransformableDia b
textBox t name reflect rotate = nameDiagram name $ transformCorrectedTextBox t (textBoxTextC colorScheme) (textBoxC colorScheme) reflect rotate
textBox :: SpecialBackend b n =>
String -> TransformableDia b n
textBox t name reflect angle = nameDiagram name $ transformCorrectedTextBox t (textBoxTextC colorScheme) (textBoxC colorScheme) reflect angle
bindTextBox :: SpecialBackend b =>
String -> SpecialQDiagram b
bindTextBox :: SpecialBackend b n =>
String -> SpecialQDiagram b n
bindTextBox = coloredTextBox (bindTextBoxTextC colorScheme) $ opaque (bindTextBoxC colorScheme)
multilineComment :: SpecialBackend b =>
multilineComment :: SpecialBackend b n =>
Colour Double
-> AlphaColour Double -> String -> SpecialQDiagram b
-> AlphaColour Double -> String -> SpecialQDiagram b n
multilineComment textColor boxColor t = lwG (0.6 * defaultLineWidth) textDia
where
textLines = lines t
@ -265,64 +261,64 @@ rectForText n = rect rectangleWidth (textBoxFontSize * textBoxHeightFactor)
-- Since the normal SVG text has no size, some hackery is needed to determine
-- the size of the text's bounding box.
coloredTextBox :: SpecialBackend b =>
coloredTextBox :: SpecialBackend b n =>
Colour Double
-> AlphaColour Double -> String -> SpecialQDiagram b
-> AlphaColour Double -> String -> SpecialQDiagram b n
coloredTextBox textColor boxColor t =
fontSize (local textBoxFontSize) (bold $ font "freemono" $ fc textColor $ text t)
<> lwG (0.6 * defaultLineWidth) (lcA boxColor $ rectForText (length t))
commentTextArea :: SpecialBackend b =>
Colour Double -> String -> SpecialQDiagram b
commentTextArea :: SpecialBackend b n =>
Colour Double -> String -> SpecialQDiagram b n
commentTextArea textColor t =
alignL $ fontSize (local textBoxFontSize) (font "freemono" $ fc textColor $ topLeftText t)
<> alignTL (lw none $ rectForText (length t))
-- ENCLOSING REGION --
enclosure :: SpecialBackend b =>
SpecialQDiagram b -> SpecialQDiagram b
enclosure :: SpecialBackend b n =>
SpecialQDiagram b n -> SpecialQDiagram b n
enclosure dia = dia <> lwG defaultLineWidth (lc (regionPerimC colorScheme) $ boundingRect (frame 0.5 dia))
-- LAMBDA ICON --
-- Don't use === here to put the port under the text box since mempty will stay
-- at the origin of the text box.
lambdaIcon ::
SpecialBackend b =>
Int -> SpecialQDiagram b
SpecialBackend b n =>
Int -> SpecialQDiagram b n
lambdaIcon x = alignB (coloredTextBox (lamArgResC colorScheme) transparent "λ") <> makePort x
-- LAMBDA REGION --
-- | lambdaRegion takes as an argument the numbers of parameters to the lambda,
-- and draws the diagram inside a region with the lambda icons on top.
lambdaRegion :: SpecialBackend b =>
Int -> SpecialQDiagram b -> SpecialQDiagram b
lambdaRegion :: SpecialBackend b n =>
Int -> SpecialQDiagram b n -> SpecialQDiagram b n
lambdaRegion n dia =
centerXY $ centerX lambdaIcons === centerX (enclosure dia)
where lambdaIcons = hsep 0.4 (take n (map lambdaIcon [0,1..]))
-- RESULT ICON --
resultIcon :: SpecialBackend b => SpecialQDiagram b
resultIcon :: SpecialBackend b n => SpecialQDiagram b n
resultIcon = lw none $ fc (lamArgResC colorScheme) unitSquare
-- BRANCH ICON --
branchIcon :: SpecialBackend b => SpecialQDiagram b
branchIcon :: SpecialBackend b n => SpecialQDiagram b n
branchIcon = lw none $ lc lineCol $ fc lineCol $ circle circleRadius
-- GUARD ICON --
guardSize :: (Fractional a) => a
guardSize = 0.7
guardTriangle :: SpecialBackend b =>
Int -> SpecialQDiagram b
guardTriangle :: SpecialBackend b n =>
Int -> SpecialQDiagram b n
guardTriangle x =
alignL $ alignR (triangleAndPort ||| lwG defaultLineWidth (hrule (guardSize * 0.8))) <> makePort x
where
triangleAndPort = alignR $ alignT $ lwG defaultLineWidth $ rotateBy (1/8) $
polygon (polyType .~ PolySides [90 @@ deg, 45 @@ deg] [guardSize, guardSize] $ with)
guardLBracket :: SpecialBackend b =>
Int -> SpecialQDiagram b
guardLBracket :: SpecialBackend b n =>
Int -> SpecialQDiagram b n
guardLBracket x = alignL (alignT ell) <> makePort x
where
ellShape = fromOffsets $ map r2 [(0, guardSize), (-guardSize,0)]
@ -333,8 +329,8 @@ guardLBracket x = alignL (alignT ell) <> makePort x
-- 1 -> bottom
-- odds -> left
-- evens -> right
generalGuardIcon :: SpecialBackend b =>
Colour Double -> (Int -> SpecialQDiagram b) -> SpecialQDiagram b -> Int -> SpecialQDiagram b
generalGuardIcon :: SpecialBackend b n =>
Colour Double -> (Int -> SpecialQDiagram b n) -> SpecialQDiagram b n -> Int -> SpecialQDiagram b n
generalGuardIcon triangleColor lBracket bottomDia n = centerXY $ alignT (bottomDia <> makePort 1) <> alignB (bigVerticalLine <> guardDia <> makePort 0)
where
--guardTriangles = vsep 0.4 (take n (map guardTriangle [0,1..]))
@ -353,19 +349,19 @@ generalGuardIcon triangleColor lBracket bottomDia n = centerXY $ alignT (bottomD
-- Port 1: Bottom result port
-- Ports 3,5...: The left ports for the booleans
-- Ports 2,4...: The right ports for the values
guardIcon :: SpecialBackend b =>
Int -> SpecialQDiagram b
guardIcon :: SpecialBackend b n =>
Int -> SpecialQDiagram b n
guardIcon = generalGuardIcon lineCol guardLBracket mempty
-- TODO Improve design to be more than a circle.
caseResult :: SpecialBackend b =>
SpecialQDiagram b
caseResult :: SpecialBackend b n =>
SpecialQDiagram b n
caseResult = lw none $ lc caseCColor $ fc caseCColor $ circle (circleRadius * 0.7)
where
caseCColor = caseRhsC colorScheme
caseC :: SpecialBackend b =>
Int -> SpecialQDiagram b
caseC :: SpecialBackend b n =>
Int -> SpecialQDiagram b n
caseC n = caseResult <> makePort n
@ -374,15 +370,15 @@ caseC n = caseResult <> makePort n
-- Port 1: Bottom result port
-- Ports 3,5...: The left ports for the results
-- Ports 2,4...: The right ports for the patterns
caseIcon :: SpecialBackend b =>
Int -> SpecialQDiagram b
caseIcon :: SpecialBackend b n =>
Int -> SpecialQDiagram b n
caseIcon = generalGuardIcon (patternC colorScheme) caseC caseResult
-- | The ports of flatLambdaIcon are:
-- 0: Result icon
-- 1: The lambda function value
-- 2,3.. : The parameters
flatLambda :: SpecialBackend b => Int -> SpecialQDiagram b
flatLambda :: SpecialBackend b n => Int -> SpecialQDiagram b n
flatLambda n = finalDia where
lambdaCircle = lwG defaultLineWidth $ lc (regionPerimC colorScheme) $ fc (regionPerimC colorScheme) $ circle circleRadius
lambdaParts = (makePort 0 <> resultIcon) : (portIcons ++ [makePort 1 <> alignR lambdaCircle])

View File

@ -31,7 +31,7 @@ import Data.Typeable(Typeable)
import Icons(colorScheme, iconToDiagram, defaultLineWidth, ColorStyle(..), portAngles)
import TranslateCore(nodeToIcon)
import Types(Edge(..), Icon, EdgeOption(..), Connection, Drawing(..), EdgeEnd(..),
NameAndPort(..), SpecialQDiagram, SpecialBackend, SyntaxNode)
NameAndPort(..), SpecialQDiagram, SpecialBackend, SyntaxNode, SpecialNum)
import Util(fromMaybeError)
-- If the inferred types for these functions becomes unweildy,
@ -48,7 +48,7 @@ graphvizScaleFactor = 0.12
--scaleFactor = 0.04
drawingToGraphvizScaleFactor :: Double
drawingToGraphvizScaleFactor :: Fractional a => a
-- For Neato, ScaleOverlaps
--drawingToGraphvizScaleFactor = 0.08
@ -120,10 +120,8 @@ getArrowOpts (t, h) opts (fromAngle, toAngle) = arrowOptions
lookupHead h $ lookupTail t with
-- | Given an Edge, return a transformation on Diagrams that will draw a line.
--connectMaybePorts :: SpecialBackend b =>
-- a -> Edge -> SpecialQDiagram b -> SpecialQDiagram b
connectMaybePorts :: (Floating n, SpecialBackend b) =>
(Angle Double, Angle Double)-> Edge -> SpecialQDiagram b -> SpecialQDiagram b
connectMaybePorts :: SpecialBackend b n =>
(Angle n, Angle n)-> Edge -> SpecialQDiagram b n -> SpecialQDiagram b n
connectMaybePorts portAngles (Edge opts ends (NameAndPort name0 mPort1, NameAndPort name1 mPort2)) =
connectFunc (getArrowOpts ends opts portAngles) qPort0 qPort1 where
(connectFunc, qPort0, qPort1) = case (mPort1, mPort2) of
@ -145,7 +143,7 @@ findPortAngles (nodeName, nodeIcon) (NameAndPort diaName mPort) = case mPort of
foundAngles = portAngles nodeIcon port mName
-- TODO Clean up the Angle arithmatic
pickClosestAngle :: (Bool, Angle Double) -> Angle Double -> Angle Double -> Angle Double -> [Angle Double] -> Angle Double
pickClosestAngle :: SpecialNum n => (Bool, Angle n) -> Angle n -> Angle n -> Angle n -> [Angle n] -> Angle n
pickClosestAngle (nodeFlip, nodeAngle) emptyCase target shaftAngle angles = case angles of
[] -> emptyCase
_ -> (-) <$>
@ -162,15 +160,15 @@ pickClosestAngle (nodeFlip, nodeAngle) emptyCase target shaftAngle angles = case
(+) <$> angle <*> nodeAngle
nodeAngle :: [((Name, Icon), (Bool, Angle Double))] -> (Name, Icon) -> (Bool, Angle Double)
nodeAngle :: Show n => [((Name, Icon), (Bool, Angle n))] -> (Name, Icon) -> (Bool, Angle n)
nodeAngle rotationMap key =
fromMaybeError ("nodeVector: key not in rotaionMap. key = " ++ show key ++ "\n\n rotationMap = " ++ show rotationMap)
$ lookup key rotationMap
makeEdge :: (SpecialBackend b, ING.Graph gr) =>
gr (Name, Icon) Edge -> SpecialQDiagram b -> [((Name, Icon), (Bool, Angle Double))] ->
ING.LEdge Edge -> SpecialQDiagram b -> SpecialQDiagram b
makeEdge :: (SpecialBackend b n, ING.Graph gr) =>
gr (Name, Icon) Edge -> SpecialQDiagram b n -> [((Name, Icon), (Bool, Angle n))] ->
ING.LEdge Edge -> SpecialQDiagram b n -> SpecialQDiagram b n
makeEdge graph dia rotationMap (node0, node1, edge@(Edge _ _ (namePort0, namePort1))) =
connectMaybePorts portAngles edge
where
@ -188,7 +186,7 @@ makeEdge graph dia rotationMap (node0, node1, edge@(Edge _ _ (namePort0, namePor
shaftVector = port1Point .-. port0Point
shaftAngle = signedAngleBetween shaftVector unitX
icon0PortAngle = pickClosestAngle node0Angle (0 @@ turn) shaftAngle shaftAngle $ findPortAngles node0label namePort0
icon0PortAngle = pickClosestAngle node0Angle mempty shaftAngle shaftAngle $ findPortAngles node0label namePort0
shaftAnglePlusOneHalf = (+) <$> shaftAngle <*> (1/2 @@ turn)
icon1PortAngle = pickClosestAngle node1Angle (1/2 @@ turn) shaftAnglePlusOneHalf shaftAngle $ findPortAngles node1label namePort1
@ -200,8 +198,8 @@ makeEdge graph dia rotationMap (node0, node1, edge@(Edge _ _ (namePort0, namePor
portAngles = (icon0PortAngle, icon1PortAngle)
addEdges :: (SpecialBackend b, ING.Graph gr) =>
gr (Name, Icon) Edge -> (SpecialQDiagram b, [((Name, Icon), (Bool, Angle Double))])-> SpecialQDiagram b
addEdges :: (SpecialBackend b n, ING.Graph gr) =>
gr (Name, Icon) Edge -> (SpecialQDiagram b n, [((Name, Icon), (Bool, Angle n))]) -> SpecialQDiagram b n
addEdges graph (dia, rotationMap) = applyAll connections dia
where
connections = makeEdge graph dia rotationMap <$> ING.labEdges graph
@ -217,10 +215,10 @@ addEdges graph (dia, rotationMap) = applyAll connections dia
-- of (this icon's port, icon that connects to this port), return the sum of the
-- distances (possibly squared) between the ports and the icons they connect to.
-- This function is used to find that angle that minimizes the sum of distances.
totalLenghtOfLines :: Double -> P2 Double -> [(P2 Double, P2 Double)] -> Double
totalLenghtOfLines :: Floating a => a -> P2 a -> [(P2 a, P2 a)] -> a
totalLenghtOfLines angle myLocation edges = sum $ map edgeDist edges
where
edgeDist :: (P2 Double, P2 Double) -> Double
--edgeDist :: (P2 Double, P2 Double) -> Double
edgeDist (relativePortLocation, iconLocation) =
-- The squaring here is arbitrary. Distance should be replaced with angle diff.
(norm $ absPortVec ^-^ iconLocationVec) ** 2
@ -235,7 +233,7 @@ totalLenghtOfLines angle myLocation edges = sum $ map edgeDist edges
-- minimizes the the sum of the distances (possibly squared) between the ports
-- and the icons they connect to. Returns (angle, sum of distances).
-- todo: Return 0 immediatly if edges == [].
angleWithMinDist :: P2 Double -> [(P2 Double, P2 Double)] -> (Double, Double)
angleWithMinDist :: SpecialNum a => P2 a -> [(P2 a, P2 a)] -> (a, a)
angleWithMinDist myLocation edges =
minimumBy (compare `on` snd) $ map totalLength [0,(1/12)..1]
where
@ -259,40 +257,40 @@ connectedPorts edges name = map edgeToPort $ filter nameInEdge edges
-- are minimized.
-- Precondition: the diagrams are already centered
-- todo: confirm precondition (or use a newtype)
rotateNodes :: SpecialBackend b =>
Map.Map (Name, Icon) (Point V2 Double)
rotateNodes :: SpecialBackend b n =>
Map.Map (Name, Icon) (Point V2 n)
-> [Connection]
-> [((Name, Icon), SpecialQDiagram b, (Bool, Angle Double))]
-> [((Name, Icon), SpecialQDiagram b n, (Bool, Angle n))]
rotateNodes positionMap edges = map rotateDiagram (Map.keys positionMap)
where
positionMapNameKeys = Map.mapKeys fst positionMap
rotateDiagram key@(name, icon) = (key, transformedDia, (flip, angle @@ turn))
rotateDiagram key@(name, icon) = (key, transformedDia, (flip, angle))
where
originalDia = iconToDiagram icon name
flip = flippedDist < unflippedDist
angle = if flip then flippedAngle else unflippedAngle
angle = (if flip then flippedAngle else unflippedAngle) @@ turn
internallTransformedDia = originalDia flip angle
transformedDia = rotateBy angle $ (if flip then reflectX else id) internallTransformedDia
transformedDia = rotate angle $ (if flip then reflectX else id) internallTransformedDia
(unflippedAngle, unflippedDist) = minAngleForDia (originalDia False 0)
(flippedAngle, flippedDist) = minAngleForDia (reflectX $ originalDia True 0)
(unflippedAngle, unflippedDist) = minAngleForDia (originalDia False mempty)
(flippedAngle, flippedDist) = minAngleForDia (reflectX $ originalDia True mempty)
--minAngleForDia :: QDiagram b V2 Double m -> (Double, Double)
minAngleForDia dia = minAngle where
--ports = Debug.Trace.trace ((show $ names dia) ++ "\n") $ names dia
ports = names dia
namesOfPortsWithLines = connectedPorts edges name
iconInMap :: (Int, Name, Maybe Int) -> Bool
--iconInMap :: (Int, Name, Maybe Int) -> Bool
iconInMap (_, otherIconName, _) = Map.member otherIconName positionMapNameKeys
getPortPoint :: Int -> P2 Double
--getPortPoint :: Int -> P2 Double
getPortPoint x =
-- TODO remove partial function head.
head $ fromMaybeError
("rotateNodes: port not found. Port: " ++ show x ++ ". Valid ports: " ++ show ports)
(lookup (name .> toName x) ports)
makePortEdge :: (Int, Name, Maybe Int) -> (P2 Double, P2 Double)
--makePortEdge :: (Int, Name, Maybe Int) -> (P2 Double, P2 Double)
makePortEdge (portInt, otherIconName, _) =
(getPortPoint portInt, getFromMapAndScale positionMapNameKeys otherIconName)
@ -303,16 +301,16 @@ rotateNodes positionMap edges = map rotateDiagram (Map.keys positionMap)
type LayoutResult a b = Gr (GV.AttributeNode (Name, b)) (GV.AttributeNode a)
placeNodes :: forall a b. SpecialBackend b =>
placeNodes :: forall a b. SpecialBackend b Double =>
LayoutResult a Icon
-> [Edge]
-> (SpecialQDiagram b, [((Name, Icon), (Bool, Angle Double))])
-> (SpecialQDiagram b Double, [((Name, Icon), (Bool, Angle Double))])
placeNodes layoutResult edges = (mconcat placedNodes, rotationMap)
where
connections = fmap edgeConnection edges
positionMap = fst $ getGraph layoutResult
-- The type annotation for rotatedNameDiagramMap is necessary here
rotatedNameDiagramMap = rotateNodes positionMap connections :: [((Name, Icon), SpecialQDiagram b, (Bool, Angle Double))]
rotatedNameDiagramMap = rotateNodes positionMap connections :: [((Name, Icon), SpecialQDiagram b Double, (Bool, Angle Double))]
rotationMap = fmap (\(x, _, z) -> (x, z)) rotatedNameDiagramMap
placedNodes = map placeNode rotatedNameDiagramMap
@ -339,11 +337,11 @@ customLayoutParams = GV.defaultParams{
GV.fmtEdge = const [GV.arrowTo GV.noArrow]
}
doGraphLayout :: forall b.
SpecialBackend b =>
doGraphLayout :: forall b n.
SpecialBackend b Double =>
Gr (Name, Icon) Edge
-> [Edge]
-> IO (SpecialQDiagram b)
-> IO (SpecialQDiagram b Double)
doGraphLayout graph edges = do
layoutResult <- layoutGraph' layoutParams GVA.Neato graph
-- layoutResult <- layoutGraph' layoutParams GVA.Fdp graph
@ -360,9 +358,9 @@ doGraphLayout graph edges = do
--[GVA.Width diaWidth, GVA.Height diaHeight]
[GVA.Width circleDiameter, GVA.Height circleDiameter]
where
-- This type annotation (:: SpecialQDiagram b) requires Scoped Typed Variables, which only works if the function's
-- This type annotation (:: SpecialQDiagram b n) requires Scoped Typed Variables, which only works if the function's
-- type signiture has "forall b e."
dia = iconToDiagram nodeIcon (toName "") False 0 :: SpecialQDiagram b
dia = iconToDiagram nodeIcon (toName "") False mempty :: SpecialQDiagram b Double
diaWidth = drawingToGraphvizScaleFactor * width dia
diaHeight = drawingToGraphvizScaleFactor * height dia
@ -372,16 +370,16 @@ doGraphLayout graph edges = do
-- | Given a Drawing, produce a Diagram complete with rotated/flipped icons and
-- lines connecting ports and icons. IO is needed for the GraphViz layout.
renderDrawing ::
SpecialBackend b =>
Drawing -> IO (SpecialQDiagram b)
SpecialBackend b Double =>
Drawing -> IO (SpecialQDiagram b Double)
renderDrawing = renderIconGraph . drawingToIconGraph
renderIngSyntaxGraph ::
SpecialBackend b =>
Gr (Name, SyntaxNode) Edge -> IO (SpecialQDiagram b)
SpecialBackend b Double =>
Gr (Name, SyntaxNode) Edge -> IO (SpecialQDiagram b Double)
renderIngSyntaxGraph = renderIconGraph . ING.nmap (Control.Arrow.second nodeToIcon)
renderIconGraph :: SpecialBackend b => Gr (Name, Icon) Edge -> IO (SpecialQDiagram b)
renderIconGraph :: SpecialBackend b Double => Gr (Name, Icon) Edge -> IO (SpecialQDiagram b Double)
renderIconGraph iconGraph = diagramAction where
edges = ING.edgeLabel <$> ING.labEdges iconGraph
diagramAction = doGraphLayout iconGraph edges

View File

@ -12,6 +12,7 @@ module Types (
IDState,
SpecialQDiagram,
SpecialBackend,
SpecialNum,
SgNamedNode,
IngSyntaxGraph,
initialIdState,
@ -21,7 +22,9 @@ module Types (
import Diagrams.Prelude(Name, QDiagram, V2, Any, Renderable, Path)
import Diagrams.TwoD.Text(Text)
import Control.Monad.State(State, state)
import Data.Typeable(Typeable)
-- TYPES --
-- | A datatype that represents an icon.
@ -75,10 +78,12 @@ data Drawing = Drawing [(Name, Icon)] [Edge] deriving (Show, Eq)
-- | IDState is an Abstract Data Type that is used as a state whose value is a unique id.
newtype IDState = IDState Int deriving (Eq, Show)
-- Note that SpecialBackend is a constraint synonym, not a type synonym.
type SpecialBackend b = (Renderable (Path V2 Double) b, Renderable (Text Double) b)
type SpecialNum n = (Floating n, RealFrac n, RealFloat n, Typeable n, Show n, Enum n)
type SpecialQDiagram b = QDiagram b V2 Double Any
-- Note that SpecialBackend is a constraint synonym, not a type synonym.
type SpecialBackend b n = (SpecialNum n, Renderable (Path V2 n) b, Renderable (Text n) b)
type SpecialQDiagram b n = QDiagram b V2 n Any
type SgNamedNode = (Name, SyntaxNode)
type IngSyntaxGraph gr = gr SgNamedNode Edge

View File

@ -459,7 +459,7 @@ translateTests :: IO (Diagram B)
translateTests = do
drawings <- traverse translateStringToDrawing testDecls
let
textDrawings = fmap (\t -> alignL $ textBox t (toName "") False 0) testDecls
textDrawings = fmap (\t -> alignL $ textBox t (toName "") False mempty) testDecls
vCattedDrawings = vsep 1 $ zipWith (===) (fmap alignL drawings) textDrawings
pure vCattedDrawings