packages feed

wumpus-tree 0.15.0 → 0.16.0

raw patch · 13 files changed

+869/−792 lines, 13 filesdep ~wumpus-basicdep ~wumpus-coredep ~wumpus-drawingPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: wumpus-basic, wumpus-core, wumpus-drawing

API changes (from Hackage documentation)

- Wumpus.Tree: charNode :: (Real u, Floating u, InterpretUnit u) => Char -> TreeNode u
- Wumpus.Tree: circleNode :: (Floating u, InterpretUnit u) => RGBi -> (a -> TreeNode u)
- Wumpus.Tree: diskNode :: (Floating u, InterpretUnit u) => RGBi -> (a -> TreeNode u)
- Wumpus.Tree: drawScaledFamilyTree :: (Real u, Floating u, InterpretUnit u, InnerSpace (Vec2 u)) => ScaleFactors u -> Point2 u -> TreeBuildAns u -> TreeDrawing u
- Wumpus.Tree: drawScaledTree :: (Real u, Floating u, InterpretUnit u, InnerSpace (Vec2 u)) => ScaleFactors u -> Point2 u -> TreeBuildAns u -> TreeDrawing u
- Wumpus.Tree: drawScaledTreeD :: (Real u, Floating u, InterpretUnit u, InnerSpace (Vec2 u)) => ScaleFactors u -> Point2 u -> TreeDirection -> TreeBuildAns u -> TreeDrawing u
- Wumpus.Tree: instance Eq TreeDirection
- Wumpus.Tree: instance Ord TreeDirection
- Wumpus.Tree: instance Show TreeDirection
- Wumpus.Tree: scaleFactors :: Num u => u -> u -> ScaleFactors u
- Wumpus.Tree: textNode :: (Real u, Floating u, InterpretUnit u) => String -> TreeNode u
- Wumpus.Tree: type ScaleFactors u = ScalingContext u Int u
- Wumpus.Tree: uniformSF :: Num u => u -> ScaleFactors u
- Wumpus.Tree.Base: Design :: CoordTree u a -> BoundingBox u -> Design u a
- Wumpus.Tree.Base: data Design u a
- Wumpus.Tree.Base: tree_bbox :: Design u a -> BoundingBox u
- Wumpus.Tree.Base: tree_design :: Design u a -> CoordTree u a
- Wumpus.Tree.Base: type CoordTree u a = Tree (Point2 u, a)
- Wumpus.Tree.Base: type DTreeDrawing = TreeDrawing Double
- Wumpus.Tree.Base: type TreeDrawing u = TraceDrawing u ()
- Wumpus.Tree.Base: type TreeNode u = DotLocImage u
- Wumpus.Tree.Design: instance Eq u => Eq (Extent u)
- Wumpus.Tree.Design: instance Eq u => Eq (HSpan u)
- Wumpus.Tree.Design: instance Ord u => Ord (HSpan u)
- Wumpus.Tree.Design: instance Show u => Show (Extent u)
- Wumpus.Tree.Design: instance Show u => Show (HSpan u)
- Wumpus.Tree.Design: rotateAboutRoot :: (Real u, Floating u) => Radian -> CoordTree u a -> CoordTree u a
- Wumpus.Tree.Draw: drawFamilyTree :: (Real u, Floating u, InterpretUnit u) => NodeAnnoRefs u -> CoordTree u (TreeNodeAns u) -> TreeDrawing u
- Wumpus.Tree.Draw: drawTree :: (Real u, Floating u, InterpretUnit u) => NodeAnnoRefs u -> CoordTree u (TreeNodeAns u) -> TreeDrawing u
- Wumpus.Tree.ScalingContext: ScalingContext :: (ux -> u) -> (uy -> u) -> ScalingContext ux uy u
- Wumpus.Tree.ScalingContext: coordinateScaling :: Num u => u -> u -> ScalingContext Int Int u
- Wumpus.Tree.ScalingContext: data ScalingContext ux uy u
- Wumpus.Tree.ScalingContext: scalePt :: ScalingContext ux uy u -> ux -> uy -> Point2 u
- Wumpus.Tree.ScalingContext: scaleVec :: ScalingContext ux uy u -> ux -> uy -> Vec2 u
- Wumpus.Tree.ScalingContext: scaleX :: ScalingContext ux uy u -> ux -> u
- Wumpus.Tree.ScalingContext: scaleY :: ScalingContext ux uy u -> uy -> u
- Wumpus.Tree.ScalingContext: scale_in_x :: ScalingContext ux uy u -> ux -> u
- Wumpus.Tree.ScalingContext: scale_in_y :: ScalingContext ux uy u -> uy -> u
- Wumpus.Tree.ScalingContext: uniformScaling :: Num u => u -> ScalingContext u u u
- Wumpus.Tree.ScalingContext: unitX :: Num ux => ScalingContext ux uy u -> u
- Wumpus.Tree.ScalingContext: unitY :: Num uy => ScalingContext ux uy u -> u
- Wumpus.Tree.TreeBuildMonad: branch :: NodeId a -> [TreeSpec a] -> TreeSpec a
- Wumpus.Tree.TreeBuildMonad: data NodeId a
- Wumpus.Tree.TreeBuildMonad: data TreeBuild u a
- Wumpus.Tree.TreeBuildMonad: instance Applicative (TreeBuild u)
- Wumpus.Tree.TreeBuildMonad: instance Eq a => Eq (NodeId a)
- Wumpus.Tree.TreeBuildMonad: instance Functor (TreeBuild u)
- Wumpus.Tree.TreeBuildMonad: instance Monad (TreeBuild u)
- Wumpus.Tree.TreeBuildMonad: label :: a -> NodeId a
- Wumpus.Tree.TreeBuildMonad: leaf :: NodeId a -> TreeSpec a
- Wumpus.Tree.TreeBuildMonad: nodeId :: TreeNode u -> TreeBuild u (NodeId a)
- Wumpus.Tree.TreeBuildMonad: regularBuild :: Tree a -> TreeBuild u (TreeSpec a)
- Wumpus.Tree.TreeBuildMonad: runTreeBuild :: (Real u, Floating u, InterpretUnit u) => (a -> TreeNode u) -> TreeBuild u (TreeSpec a) -> TreeBuildAns u
- Wumpus.Tree.TreeBuildMonad: type NodeAnno u = DotAnchor u -> Graphic u
- Wumpus.Tree.TreeBuildMonad: type NodeAnnoRefs u = IntMap (NodeAnno u)
- Wumpus.Tree.TreeBuildMonad: type TreeBuildAns u = (Tree (TreeNodeAns u), NodeAnnoRefs u)
- Wumpus.Tree.TreeBuildMonad: type TreeNodeAns u = (TreeNode u, Maybe Int)
- Wumpus.Tree.TreeBuildMonad: type TreeSpec a = Tree (NodeId a)
- Wumpus.Tree.TreeBuildMonad: type ZNodeId u = NodeId (UNil u)
- Wumpus.Tree.TreeBuildMonad: type ZTreeSpec u = TreeSpec (UNil u)
- Wumpus.Tree.TreeBuildMonad: zbranch :: [ZTreeSpec u] -> ZTreeSpec u
- Wumpus.Tree.TreeBuildMonad: zleaf :: ZTreeSpec u
+ Wumpus.Tree: runTreeLoc :: (Real u, Floating u, InterpretUnit u) => TreeProps u a -> (elt -> LocImage u a) -> Tree elt -> LocGraphic u
+ Wumpus.Tree: standardTreeProps :: Fractional u => u -> u -> OTMAnchorConn u a -> TreeProps u a
+ Wumpus.Tree: tree_direction :: TreeDirection -> TreePropsF u a
+ Wumpus.Tree.Base: TREE_DOWN :: TreeDirection
+ Wumpus.Tree.Base: TREE_LEFT :: TreeDirection
+ Wumpus.Tree.Base: TREE_RIGHT :: TreeDirection
+ Wumpus.Tree.Base: TREE_UP :: TreeDirection
+ Wumpus.Tree.Base: TreeProps :: u -> u -> OTMAnchorConn u a -> TreeDirection -> TreeProps u a
+ Wumpus.Tree.Base: data TreeDirection
+ Wumpus.Tree.Base: data TreeProps u a
+ Wumpus.Tree.Base: getTreeConnector :: (DrawingCtxM m, InterpretUnit u) => TreeProps u a -> m (a -> [a] -> Graphic u)
+ Wumpus.Tree.Base: instance Eq TreeDirection
+ Wumpus.Tree.Base: instance Ord TreeDirection
+ Wumpus.Tree.Base: instance Show TreeDirection
+ Wumpus.Tree.Base: tp_direction :: TreeProps u a -> TreeDirection
+ Wumpus.Tree.Base: tp_level_distance :: TreeProps u a -> u
+ Wumpus.Tree.Base: tp_multiconn :: TreeProps u a -> OTMAnchorConn u a
+ Wumpus.Tree.Base: tp_sibling_distance :: TreeProps u a -> u
+ Wumpus.Tree.Base: tree_direction :: TreeDirection -> TreePropsF u a
+ Wumpus.Tree.Base: type OTMAnchorConn u a = TreeDirection -> u -> a -> [a] -> Graphic u
+ Wumpus.Tree.Base: type TreePropsF u a = TreeProps u a -> TreeProps u a
+ Wumpus.Tree.Design: data UW
+ Wumpus.Tree.Design: instance Eq Extent
+ Wumpus.Tree.Design: instance Eq HSpan
+ Wumpus.Tree.Design: instance Eq UW
+ Wumpus.Tree.Design: instance Floating UW
+ Wumpus.Tree.Design: instance Fractional UW
+ Wumpus.Tree.Design: instance InterpretUnit UW
+ Wumpus.Tree.Design: instance Num UW
+ Wumpus.Tree.Design: instance Ord HSpan
+ Wumpus.Tree.Design: instance Ord UW
+ Wumpus.Tree.Design: instance Real UW
+ Wumpus.Tree.Design: instance RealFloat UW
+ Wumpus.Tree.Design: instance RealFrac UW
+ Wumpus.Tree.Design: instance Show Extent
+ Wumpus.Tree.Design: instance Show HSpan
+ Wumpus.Tree.Design: instance Show UW
+ Wumpus.Tree.Design: orientateTree :: (Real u, Floating u) => TreeDirection -> Tree (Point2 u, a) -> Tree (Point2 u, a)
+ Wumpus.Tree.Design: scaleTree :: (DrawingCtxM m, InterpretUnit u) => u -> u -> CoordTree a -> m (Tree (Point2 u, a))
+ Wumpus.Tree.Design: type CoordTree a = Tree (Point2 UW, a)
+ Wumpus.Tree.DrawLoc: runTreeLoc :: (Real u, Floating u, InterpretUnit u) => TreeProps u a -> (elt -> LocImage u a) -> Tree elt -> LocGraphic u
+ Wumpus.Tree.OTMConnectors: blankOTMC :: (Real u, Floating u, InterpretUnit u, CenterAnchor a, u ~ (DUnit a)) => OTMAnchorConn u a
+ Wumpus.Tree.OTMConnectors: familyOTMC :: (Real u, Floating u, Ord u, Tolerance u, InterpretUnit u, CenterAnchor a, CardinalAnchor a, u ~ (DUnit a)) => OTMAnchorConn u a
+ Wumpus.Tree.OTMConnectors: radialOTMC :: (Real u, Floating u, InterpretUnit u, CenterAnchor a, RadialAnchor a, u ~ (DUnit a)) => OTMAnchorConn u a
+ Wumpus.Tree.OTMConnectors: splayOTMC :: (Real u, Floating u, Ord u, Tolerance u, InterpretUnit u, CenterAnchor a, CardinalAnchor a, u ~ (DUnit a)) => OTMAnchorConn u a
+ Wumpus.Tree.TreeBuilder: data TbNode u a
+ Wumpus.Tree.TreeBuilder: data TreeSpec node u a
+ Wumpus.Tree.TreeBuilder: drawTreeSpec :: (Real u, Floating u, InterpretUnit u, DrawingCtxM m, TraceM m, u ~ (MonUnit (m ()))) => TreeProps u node -> Point2 u -> AbsTreeSpec u node -> m ()
+ Wumpus.Tree.TreeBuilder: instance Applicative (Builder node u)
+ Wumpus.Tree.TreeBuilder: instance Applicative (MonBase node u)
+ Wumpus.Tree.TreeBuilder: instance Applicative (TreeSpec node u)
+ Wumpus.Tree.TreeBuilder: instance DrawingCtxM (Builder node u)
+ Wumpus.Tree.TreeBuilder: instance Functor (Builder node u)
+ Wumpus.Tree.TreeBuilder: instance Functor (MonBase node u)
+ Wumpus.Tree.TreeBuilder: instance Functor (TreeSpec node u)
+ Wumpus.Tree.TreeBuilder: instance Monad (Builder node u)
+ Wumpus.Tree.TreeBuilder: instance Monad (MonBase node u)
+ Wumpus.Tree.TreeBuilder: instance Monad (TreeSpec node u)
+ Wumpus.Tree.TreeBuilder: instance TraceGraphicM (Builder node u)
+ Wumpus.Tree.TreeBuilder: leaf :: TbNode u node -> RefTree u node
+ Wumpus.Tree.TreeBuilder: linkref :: TbNode u node -> TbNode u node -> LinkDraw u node -> TreeSpec node u ()
+ Wumpus.Tree.TreeBuilder: mkleaf :: LocImage u node -> RefTree u node
+ Wumpus.Tree.TreeBuilder: ref :: LocImage u node -> TreeSpec node u (TbNode u node)
+ Wumpus.Tree.TreeBuilder: root :: TbNode u node -> [RefTree u node] -> RefTree u node
+ Wumpus.Tree.TreeBuilder: type AbsTreeSpec u node = TreeSpec node u (RefTree u node)
- Wumpus.Tree.Design: design :: (Fractional u, Ord u) => Point2 u -> ScalingContext u Int u -> Tree a -> CoordTree u a
+ Wumpus.Tree.Design: design :: Tree a -> CoordTree a

Files

CHANGES view
@@ -1,3 +1,46 @@+0.14.0 to 0.15.0:++  * Updated to work with latest Wumpus libraries. +    @ScalingContext@ has been temporarily added from Wumpus-Basic +    (it was considered obsolete there). At some point the +    functionality needs re-implementing so it can be removed from +    Tree.+  +0.13.0 to 0.14.0:++  * Updated to work with latest Wumpus libraries. ++0.12.0 to 0.13.0:++  * Changed the specification of trees so that they are built in a+    monad. The bind operation of the monad allows /anchors/ to be +    extracted from tree nodes so they can be annotated with +    supplementary graphics. At the moment this is rather limited +    as Wumpus-Basic and Wumpus-Drawing do not offer much support +    for anchors other than the basic type classes.++  * Changed the type of the rendering functions so they produce a +    TreeDrawing. This type is more suitable for building composite+    pictures than the previous type TreePicture. ++  * Also the rendering functions now take a start point for the +    root node, again this should be more convenient for drawing +    composite pictures - see the demo which now draws all the +    example trees on one page.++  * Internally the tree design is now more flexible - trees can be +    designed upwards or leftwards rightwards, rather than just +    downwards; and edge drawing style is lifted out of the +    rendering to use a supplied combinator. Currently these +    features are not exposed by the API, the API needs more +    thought (possibly warranting changes to Wumpus-Basic and +    Wumpus-Drawing).+++0.11.1 to 0.12.0:++  * Internal changes to track updates to Wumpus-Basic.+   0.11.0 to 0.11.1: 
demo/Demo01.hs view
@@ -1,23 +1,13 @@ {-# OPTIONS -Wall #-} --- Note - @main@ is more convoluted than would normally be --- expected as it supports both sources of glyph metrics - the --- GhostScript distribution or the Core 14 metrics from Adobe.--- --- \"Real\" applications would be expected to choose one source. ------ I-am-not-a-lawyer, but it does look as though the Adobe font--- metrics are redistributable, the GhostScript metrics are --- seemingly redistributable under the same terms as the larger--- GhostScript distribution.---   module Demo01 where  import Wumpus.Tree-import Wumpus.Tree.TreeBuildMonad+-- import Wumpus.Tree.TreeBuildMonad  import Wumpus.Drawing.Colour.SVGColours         -- package: wumpus-drawing+import Wumpus.Drawing.Dots.AnchorDots import Wumpus.Drawing.Text.StandardFontDefs  import Wumpus.Basic.Kernel                      -- package: wumpus-basic@@ -35,7 +25,7 @@ main1 :: FontLoader -> IO () main1 loader = do     createDirectoryIfMissing True "./out/" -    base_metrics <- loader [ Right helvetica_family ]+    base_metrics <- loader [ Right times_roman_family ]     printLoadErrors base_metrics     let pic1 = runCtxPictureU (makeCtx 18 base_metrics) tree_pic1     writeEPS "./out/regular_tree01.eps"  pic1@@ -50,39 +40,44 @@ tree_pic1 :: CtxPicture tree_pic1 = udrawTracing (0::Double) $ do     ---    draw $ plainTextLine "Tree 1:"        `at` (P2 0  530)-    drawScaledTree (uniformSF 30)         (P2 80 530) $ -       runTreeBuild charNode tree1+    draw $ dcTextlabel "Tree 1:"        `at` (P2 0  550)+    drawl (P2 10 500) $ runTreeLoc props1 (const red_dot) tree1     ---    draw $ plainTextLine "Tree 2:"       `at` (P2 160 530) -    drawScaledTree (uniformSF 30)        (P2 240 530) $ -        runTreeBuild (diskNode red) tree2+    draw $ dcTextlabel "Tree 2:"       `at` (P2 200 550) +    drawl (P2 300 550) $ runTreeLoc props2 dotChar tree2 -    draw $ plainTextLine "Tree 3:"       `at` (P2 0  410) +    draw $ dcTextlabel "Tree 3:"       `at` (P2 0  410)      localize (set_font_size 12) $ -        drawScaledFamilyTree (uniformSF 25) (P2 280 410) $ -          runTreeBuild charNode tree3+        drawl (P2 280 410) $ runTreeLoc props3 dotChar tree3      ---    draw $ plainTextLine "Tree 4:"       `at` (P2 0  200)-    drawScaledTree (scaleFactors 20 30)  (P2 80 200) $ -        runTreeBuild (circleNode black) tree4+    draw $ dcTextlabel "Tree 4:"       `at` (P2 0  190)+    drawl (P2 80 190) $ runTreeLoc props4 (const circ_dot) tree4     ---    draw $ plainTextLine "Tree 5:"        `at` zeroPt-    drawScaledTree (scaleFactors 20 30)  (P2 240 0) $-        runTreeBuild (circleNode black)  tree5+    draw $ dcTextlabel "Tree 5:"        `at` zeroPt+    drawl (P2 320 0) $ runTreeLoc props5 (const circ_dot) tree5+  where+    red_dot  = localize (fill_colour red) dotDisk+    circ_dot = localize (stroke_colour black) dotCircle +    props1 = tree_direction TREE_RIGHT $ standardTreeProps 30 30 radialOTMC+    props2 = standardTreeProps 30 40 familyOTMC+    props3 = tree_direction TREE_DOWN $ standardTreeProps 25 30 familyOTMC+    props4 = standardTreeProps 20 30 radialOTMC+    props5 = standardTreeProps 30 36 radialOTMC  -tree1 :: TreeBuild u (TreeSpec Char)-tree1 = regularBuild $ Node 'A' [Node 'B' bs, Node 'F' fs]+tree1 :: Tree Char+tree1 = Node 'A' [Node 'B' bs, Node 'F' fs]   where     bs = [Node 'C' [], Node 'D' [], Node 'E' []]     fs = [Node 'G' [Node 'H' [], Node 'I' [], Node 'J' []]]  -tree2 :: TreeBuild u (TreeSpec Char)-tree2 = regularBuild $ Node 'A' [Node 'B' bs, Node 'F' [], Node 'G' gs]+++tree2 :: Tree Char+tree2 = Node 'A' [Node 'B' bs, Node 'F' [], Node 'G' gs]   where     bs = [Node 'C' [], Node 'D' [], Node 'E' []]     gs = [Node 'H' [], Node 'I' [], Node 'J' []]@@ -91,8 +86,10 @@ -- This is the tree from Andrew Kennedy's  -- /Functional Pearl Drawing Trees/ ---tree3 :: TreeBuild u (TreeSpec Char)-tree3 = regularBuild $ Node 'A' [a1, a2, a3]+-- Draw with dotChar.+--+tree3 :: Tree Char+tree3 = Node 'A' [a1, a2, a3]   where     a1 = Node 'B' [b1, b2]     a2 = Node 'S' [b3,b4]@@ -123,8 +120,8 @@ -- This is the tree (a) T3 from Buchheim, Junger and Leipert -- /Improving Walker\'s Algorithm to Run in Linear Time/. -- -tree4 :: TreeBuild u (TreeSpec Int)-tree4 = regularBuild $ Node 1 [a1, a2]+tree4 :: Tree Int+tree4 = Node 1 [a1, a2]   where     a1 = Node  2 [b1]     a2 = Node  3 [b2, b3]@@ -137,6 +134,7 @@     d1 = Node 11 [tleaf 14]     d2 = Node 13 [tleaf 15] + -- This is the tree (b) T3 from Buchheim, Junger and Leipert -- /Improving Walker\'s Algorithm to Run in Linear Time/. -- @@ -144,8 +142,8 @@ -- spaces the leaves, it looks like the trees in that paper are  -- evenly spaced at the interior nodes too. -- -tree5 :: TreeBuild u (TreeSpec Int)-tree5 = regularBuild $+tree5 :: Tree Int+tree5 =      Node 1 [a1, tleaf 3, tleaf 4, tleaf 5, a2, tleaf 7, tleaf 8, tleaf 9, a3]   where     a1 = Node  2 [ tleaf 11, tleaf 12, tleaf 13, tleaf 14, tleaf 15, tleaf 16
src/Wumpus/Tree.hs view
@@ -1,170 +1,49 @@-{-# LANGUAGE TypeFamilies               #-}-{-# LANGUAGE FlexibleContexts           #-} {-# OPTIONS -Wall #-}  -------------------------------------------------------------------------------- -- | -- Module      :  Wumpus.Tree--- Copyright   :  (c) Stephen Tetley 2010+-- Copyright   :  (c) Stephen Tetley 2010-2011 -- License     :  BSD3 -- -- Maintainer  :  Stephen Tetley <stephen.tetley@gmail.com> -- Stability   :  highly unstable -- Portability :  GHC --+-- Note - this module is a kludge whilst I work out a usable API.+--  --------------------------------------------------------------------------------  module Wumpus.Tree   (-  -- * The type of rendered trees--    ScaleFactors-  , uniformSF-  , scaleFactors--  , drawScaledTree-  , TreeDirection(..)-  , drawScaledTreeD--  , drawScaledFamilyTree+  -- * Re-exports+    module Wumpus.Tree.OTMConnectors +  , TreeDirection(..) +  , tree_direction+  , runTreeLoc -  -- * Drawing nodes-  , charNode-  , textNode-  , circleNode-  , diskNode+  -- * Definitions+  , standardTreeProps    )   where  import Wumpus.Tree.Base-import Wumpus.Tree.Design-import Wumpus.Tree.Draw-import Wumpus.Tree.ScalingContext-import Wumpus.Tree.TreeBuildMonad+import Wumpus.Tree.DrawLoc+import Wumpus.Tree.OTMConnectors -import Wumpus.Basic.Kernel                      -- package: wumpus-basic-import Wumpus.Drawing.Dots.AnchorDots -import Wumpus.Core                              -- package: wumpus-core -import Data.VectorSpace                         -- package: vector-space   ---- | Customize the size of the printed tree.------ A tree is /designed/ with a height of 1 unit between --- parent and child nodes.------ The y-scaling factor multiplies the unit height, a scaling --- factor of 30 represents 30 /points/.------ In the horizontal, 1 unit is the smallest possible distance --- between child nodes.----type ScaleFactors u = ScalingContext u Int u------- | Build uniform x- and y-scaling factors, i.e. @ x == y @.----uniformSF :: Num u => u -> ScaleFactors u-uniformSF u = ScalingContext (\x -> u * x)-                             (\y -> u * fromIntegral y) ---scaleFactors :: Num u => u -> u -> ScaleFactors u-scaleFactors sx sy = ScalingContext (\x -> sx * x)-                                    (\y -> sy * fromIntegral y)	------ --drawScaledTree :: (Real u, Floating u, InterpretUnit u, InnerSpace (Vec2 u)) -               => ScaleFactors u -> Point2 u -> TreeBuildAns u -               -> TreeDrawing u-drawScaledTree scale_f ogin (tree,annos) = -    drawTree annos $ design ogin scale_f tree----data TreeDirection = TREE_UP | TREE_DOWN | TREE_LEFT | TREE_RIGHT-  deriving (Eq,Ord,Show)--drawScaledTreeD :: (Real u, Floating u, InterpretUnit u, InnerSpace (Vec2 u)) -                => ScaleFactors u -> Point2 u -                -> TreeDirection -> TreeBuildAns u -                -> TreeDrawing u-drawScaledTreeD scale_f ogin tdir (tree,annos) = -    drawTree annos $ rotTree tdir $ design ogin scale_f tree-----rotTree :: (Real u, Floating u) -        => TreeDirection -> CoordTree u a -> CoordTree u a-rotTree TREE_UP     = rotateAboutRoot pi-rotTree TREE_DOWN   = id-rotTree TREE_LEFT   = rotateAboutRoot (1.5*pi)-rotTree TREE_RIGHT  = rotateAboutRoot (0.5*pi)-----drawScaledFamilyTree :: (Real u, Floating u, InterpretUnit u, InnerSpace (Vec2 u)) -               => ScaleFactors u -> Point2 u -> TreeBuildAns u -               -> TreeDrawing u-drawScaledFamilyTree scale_f ogin (tree,annos) = -    drawFamilyTree annos $ design ogin scale_f tree------------------------------------------------------------------------------------- Drawing functions---- | Render tree nodes with a single character.------  Useful for rendering @ Data.Tree Char @.----charNode :: (Real u, Floating u, InterpretUnit u) -         => Char -> TreeNode u-charNode = dotChar----- | Tree nodes with a text label.------ Useful for rendering @ Data.Tree String @.------ Note the width of the label is not accounted for in the --- /design/ of the tree. Labels with long texts may overlap.--- Also, only a single line of text is printed - any text after --- the first newline character will be dropped.----textNode :: (Real u, Floating u, InterpretUnit u) -         => String -> TreeNode u-textNode = dotText . uptoNewline-  where-    uptoNewline = takeWhile (/='\n')---- | Tree nodes with a stroked circle.------ Suitable for printing the shape of a tree, ignoring the data.----circleNode :: (Floating u, InterpretUnit u) -           => RGBi -> (a -> TreeNode u)-circleNode rgb = \_ -> localize (stroke_colour rgb) dotCircle----- | Tree nodes with a filled circle.------ Suitable for printing the shape of a tree, ignoring the data.----diskNode :: (Floating u, InterpretUnit u) -         => RGBi -> (a -> TreeNode u)-diskNode rgb = \_ -> localize (fill_colour rgb) dotDisk--+standardTreeProps :: Fractional u +                  => u -> u -> OTMAnchorConn u a -> TreeProps u a+standardTreeProps sx sy otm_conn = +    TreeProps { tp_sibling_distance = sx +              , tp_level_distance   = sy+              , tp_multiconn        = otm_conn         +              , tp_direction        = TREE_DOWN+              }   
src/Wumpus/Tree/Base.hs view
@@ -4,7 +4,7 @@ -------------------------------------------------------------------------------- -- | -- Module      :  Wumpus.Tree.Base--- Copyright   :  (c) Stephen Tetley 2010+-- Copyright   :  (c) Stephen Tetley 2010-2011 -- License     :  BSD3 -- -- Maintainer  :  stephen.tetley@gmail.com@@ -18,52 +18,43 @@ module Wumpus.Tree.Base   ( -    TreeDrawing-  , DTreeDrawing-  , CoordTree-  -  , TreeNode--  , Design(..)+    OTMAnchorConn+  , TreeProps(..)+  , TreePropsF+  , TreeDirection(..)+  , tree_direction+  , getTreeConnector    ) where -import Wumpus.Basic.Kernel                      -- package: wumpus-basic-import Wumpus.Drawing.Dots.AnchorDots -import Wumpus.Core                              -- package: wumpus-core -import Data.Tree----- | A rendered tree - alias for for @Picture Double@ in --- Wumpus-Core.----type TreeDrawing u      = TraceDrawing u ()--type DTreeDrawing       = TreeDrawing Double-+import Wumpus.Basic.Kernel                      -- package: wumpus-basic  +type OTMAnchorConn u a = TreeDirection -> u -> a -> [a] -> Graphic u  --- | Tree annotated with positions.----type CoordTree u a = Tree (Point2 u, a)+data TreeProps u a = TreeProps+      { tp_sibling_distance :: u+      , tp_level_distance   :: u+      , tp_multiconn        :: OTMAnchorConn u a+      , tp_direction        :: TreeDirection+      }   +type TreePropsF u a = TreeProps u a -> TreeProps u a +data TreeDirection = TREE_UP | TREE_DOWN | TREE_LEFT | TREE_RIGHT+  deriving (Eq,Ord,Show) --- | Tree nodes are currently a /Dot/ from Wumpus-Drawing.------ At some point this should change to allow any object that --- supports anchors.----type TreeNode u = DotLocImage u+tree_direction :: TreeDirection -> TreePropsF u a+tree_direction dir props = props { tp_direction = dir }  -data Design u a = Design -      { tree_design     :: CoordTree u a-      , tree_bbox       :: BoundingBox u-      }-+getTreeConnector :: (DrawingCtxM m, InterpretUnit u)+                 => TreeProps u a -> m (a -> [a] -> Graphic u)+getTreeConnector (TreeProps { tp_level_distance   = lvl+                            , tp_multiconn        = conn+                            , tp_direction        = dir  }) = +    uconvertCtx1 lvl >>= \ulvl -> return (conn dir ulvl) 
src/Wumpus/Tree/Design.hs view
@@ -1,10 +1,11 @@+{-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE ScopedTypeVariables        #-} {-# OPTIONS -Wall #-}  -------------------------------------------------------------------------------- -- | -- Module      :  Wumpus.Tree.Design--- Copyright   :  (c) Stephen Tetley 2010+-- Copyright   :  (c) Stephen Tetley 2010-2011 -- License     :  BSD3 -- -- Maintainer  :  Stephen Tetley <stephen.tetley@gmail.com>@@ -25,14 +26,22 @@  module Wumpus.Tree.Design   (-    design-  , rotateAboutRoot++  -- * Design a tree+    UW+  , CoordTree+  , design++  -- * Post transform a tree design+  , scaleTree+  , orientateTree+   )   where  import Wumpus.Tree.Base-import Wumpus.Tree.ScalingContext +import Wumpus.Basic.Kernel              -- package: wumpus-basic  import Wumpus.Core                      -- package: wumpus-core @@ -41,53 +50,77 @@ import Data.Tree  +-- | Tree unit width.+-- +-- Trees are designed with 1.0 as the ideal width between nodes.+-- This is represented as a specific newtype so it can be +-- contextually scaled after the design, before the tree is drawn.+--+newtype UW = UW { getUW :: Double }+  deriving (Eq,Ord,Num,Floating,Fractional,Real,RealFrac,RealFloat) +instance Show UW where+  showsPrec p d = showsPrec p (getUW d) +instance InterpretUnit UW where+  normalize _ = realToFrac+  dinterp   _ = realToFrac+++++-- | Tree annotated with positions.+-- +-- This is the result of 'design'.+--+type CoordTree a = Tree (Point2 UW, a)++ -- | XPos is an absolute position ---type XPos u = u     +type XPos = UW -type XTree u a = Tree (XPos u, a)+type XTree a = Tree (XPos, a)   -- | Delta - difference in X-positions. ---type Delta u = u+type Delta = UW  -- A horizontal span. ---data HSpan u = HSpan !u !u+data HSpan = HSpan !UW !UW   deriving (Eq,Ord,Show)   -outsideMerge :: HSpan u -> HSpan u -> HSpan u+outsideMerge :: HSpan -> HSpan -> HSpan outsideMerge (HSpan p _) (HSpan _ q) = HSpan p q    -moveSpan :: Num u => Delta u -> HSpan u -> HSpan u+moveSpan :: Delta -> HSpan -> HSpan moveSpan d (HSpan p q) = HSpan (p+d) (q+d)  -newtype Extent u = Extent { span_list :: [HSpan u] }+newtype Extent = Extent { span_list :: [HSpan] }   deriving (Eq,Show)  -extlink :: u -> Extent u -> Extent u+extlink :: UW -> Extent -> Extent extlink a (Extent as) = Extent $ (HSpan a a) :as   -- note is this just for left ... ? ---midtop :: Fractional u => u -> Extent u -> XPos u+midtop :: UW -> Extent -> XPos midtop r (Extent [])        = r midtop _ (Extent (HSpan p q:_)) = p + (0.5*(q-p))   -- merge \"moving right\"... ---mergeMR :: Num u => Delta u -> Extent u -> Extent u -> Extent u+mergeMR :: Delta -> Extent -> Extent -> Extent mergeMR dx (Extent xs) (Extent ys) = Extent $ step xs ys   where     step ps     []     = ps@@ -96,7 +129,7 @@  -- dx is negative... ---mergeML :: Num u => Delta u -> Extent u -> Extent u -> Extent u+mergeML :: Delta-> Extent -> Extent -> Extent mergeML dx (Extent xs) (Extent ys) = Extent $ step xs ys   where     step ps     []     = map (moveSpan dx) ps@@ -105,24 +138,23 @@   -extentZero :: Extent u+extentZero :: Extent extentZero = Extent [] -extentOne :: XPos u -> Extent u+extentOne :: XPos -> Extent extentOne x = Extent [HSpan x x]   -- 'moveTree' is now recursive... ---moveTree :: Num u => Delta u -> XTree u a -> XTree u a+moveTree :: Delta -> XTree a -> XTree a moveTree dx (Node (x,a) subtrees) = Node ((x+dx),a) subtrees'   where     subtrees' = map (moveTree dx) subtrees   -fit :: (Fractional u, Ord u) -    => Extent u -> Extent u -> u+fit :: Extent -> Extent -> UW fit a b = go (span_list a) (span_list b) 0.0    where     go (HSpan _ p:ps) (HSpan q _:qs) acc = go ps qs (max acc (p - q + 1.0))@@ -132,8 +164,7 @@ -- Fitting the children of a node...  -fitleft :: (Fractional u, Ord u) -        => [(XTree u a,Extent u)] -> ([XTree u a], Extent u)+fitleft :: [(XTree a,Extent)] -> ([XTree a], Extent) fitleft []           = ([],extentZero) fitleft ((l,ext):xs) = (l:ts,ext') -- left-most child unchanged    where @@ -142,8 +173,7 @@      step aex (t,ex)  = let dx = fit aex ex                          in (mergeMR dx aex ex, moveTree dx t) -fitright :: (Fractional u, Ord u) -         => [(XTree u a, Extent u)] -> ([XTree u a], Extent u)+fitright :: [(XTree a, Extent)] -> ([XTree a], Extent) fitright = post . foldr fn Nothing   where     post                        = fromMaybe ([],extentZero)@@ -156,35 +186,38 @@   --- Note - this will tell how wide the tree is...--- though the last exten is not necessarily the widest. -designl :: forall a u. (Fractional u, Ord u) -        => Tree a -> (XTree u a, Extent u)+-- | Design the tree from the left.+-- +-- Left and right tree designs are merged.+--+designl :: forall a. Tree a -> (XTree a, Extent) designl (Node a [])   = (Node (0.0,a)  [],    extentOne 0.0) designl (Node a kids) = (Node (xpos,a) kids', ext1)   where-    xs              :: [(XTree u a, Extent u)]+    xs              :: [(XTree a, Extent)]     xs              = map designl kids -    kids'           :: [XTree u a]-    ext0, ext1      :: Extent u+    kids'           :: [XTree a]+    ext0, ext1      :: Extent     (kids',ext0)    = fitleft xs      xpos            = midtop 0.0 ext0     ext1            = xpos `extlink` ext0 --designr :: forall u a. (Fractional u, Ord u) -        => XPos u -> Tree a -> (XTree u a, Extent u)+-- | Design the tree from the right.+-- +-- Right and left tree designs are merged.+--+designr :: forall a. XPos -> Tree a -> (XTree a, Extent) designr r (Node a [])   = (Node (r,a)  [],    extentOne r) designr r (Node a kids) = (Node (xpos,a) kids', ext1)   where-    xs              :: [(XTree u a, Extent u)]+    xs              :: [(XTree a, Extent)]     xs              = map (designr r) kids -    kids'           :: [XTree u a]-    ext0, ext1      :: Extent u+    kids'           :: [XTree a]+    ext0, ext1      :: Extent     (kids',ext0)    = fitright xs      xpos            = midtop r ext0@@ -199,9 +232,8 @@ -- 1.0 separating nodes it is rescaled as a post-processing step -- into drawable coordinates.  ---design :: (Fractional u, Ord u)-       => Point2 u -> ScalingContext u Int u -> Tree a -> CoordTree u a-design ro sctx t = rootOrientate ro $ scaleDesign sctx 0 t3+design :: Tree a -> CoordTree a+design t = rootOrientate zeroPt $ decorateYPosns 0 t3   where     (t1,ext)                    = designl t     (_, HSpan xmin xmax)        = stats ext@@ -213,41 +245,28 @@     zfn (x0,a) (x1,_)           = (mean x0 x1,a)  --- Scale the tree. Originally the tree has no y-positions (but by --- recursion they can be counted) and x-positions are respective --- to the unit width 1.0.+-- Originally the tree has no y-positions, recurse through the +-- tree adding them... ---scaleDesign :: Num uy -            => ScalingContext ux uy u -> uy -> Tree (XPos ux, a) -> CoordTree u a-scaleDesign ctx lvl (Node (xpos,a) kids) = Node (pt,a) kids'+decorateYPosns :: UW -> Tree (XPos, a) -> CoordTree a+decorateYPosns lvl (Node (xpos,a) kids) = Node (pt,a) kids'   where-    pt    = scalePt ctx xpos lvl-    kids' = map (scaleDesign ctx (lvl-1)) kids+    pt    = P2 xpos lvl+    kids' = map (decorateYPosns (lvl-1)) kids            -rootOrientate :: Num u => Point2 u -> CoordTree u a -> CoordTree u a+rootOrientate :: Point2 UW -> CoordTree a -> CoordTree a rootOrientate (P2 ox oy) (Node (P2 x0 y0, val) kids) =      Node (P2 ox oy, val) $ map (mv (ox-x0) (oy-y0)) kids   where     mv dx dy (Node (P2 x y, a) ks) = let ks' = map (mv dx dy) ks                                       in Node (P2 (x+dx) (y+dy), a) ks' --- Updating this to the latest Wumpus-Basic would make the --- function a query...----rotateAboutRoot :: (Real u, Floating u) -                => Radian -> CoordTree u a -> CoordTree u a-rotateAboutRoot ang (Node (ogin,val) kids) =-    Node (ogin, val) $ map step kids-  where-    step (Node (p0, a) ks) = Node (rotA p0, a) $ map step ks -    rotA                   = rotateAbout ang ogin- -- find height and width ---stats :: (Num u, Ord u) => Extent u -> (Int, HSpan u)+stats :: Extent -> (Int, HSpan) stats (Extent [])     = (0,HSpan 0 0) stats (Extent (e:es)) = foldr fn (1,e) es   where@@ -257,7 +276,7 @@ mean x y = (x+y) / 2.0  -minmaxMerge :: Ord u => HSpan u -> HSpan u -> HSpan u+minmaxMerge :: HSpan -> HSpan -> HSpan minmaxMerge (HSpan p q) (HSpan p' q') = HSpan (min p p') (max q q')  @@ -266,6 +285,53 @@   where     step (p:ps) (q:qs) = treeZipWith f p q : step ps qs     step _      _      = [] ++++++--------------------------------------------------------------------------------+-- Post design transformations...+++-- | 'scaleTree' : @ sibling_distance * level_distance * CoordTree -> Tree @+--+-- Scale a CoordTree - this forms a tree where the node label+-- is a pair of @Point2 u@ and an @a@ (usually a LocImage).+-- +scaleTree :: (DrawingCtxM m, InterpretUnit u)+          => u -> u -> CoordTree a -> m (Tree (Point2 u, a))+scaleTree sib_dist lvl_dist tree = +    getFontSize >>= \sz -> +    let fn = mkFun sz in return $ fmap (bimapL fn) tree+  where+    mkFun sz = \(P2 x y) -> let ux = sib_dist * (dinterp sz $ realToFrac x)+                                uy = lvl_dist * (dinterp sz $ realToFrac y)+                            in P2 ux uy+++++-- | Orientate the Tree according to it\'s drawing direction.+-- +-- This is a rotation about the root node.+--+orientateTree :: (Real u, Floating u)+              => TreeDirection -> Tree (Point2 u, a) -> Tree (Point2 u, a)+orientateTree TREE_DOWN  tree = tree+orientateTree TREE_UP    tree = rotateAboutRoot pi tree+orientateTree TREE_LEFT  tree = rotateAboutRoot (1.5*pi) tree+orientateTree TREE_RIGHT tree = rotateAboutRoot (0.5*pi) tree+++rotateAboutRoot :: (Real u, Floating u)+                => Radian -> Tree (Point2 u, a) -> Tree (Point2 u, a)+rotateAboutRoot ang (Node (ogin,val) kids) =+    Node (ogin, val) $ map step kids+  where+    step (Node (v0, a) ks) = Node (rotA v0, a) $ map step ks++    rotA                   = rotateAbout ang ogin   
− src/Wumpus/Tree/Draw.hs
@@ -1,152 +0,0 @@-{-# LANGUAGE TypeFamilies               #-}-{-# LANGUAGE FlexibleContexts           #-}-{-# OPTIONS -Wall #-}------------------------------------------------------------------------------------- |--- Module      :  Wumpus.Tree.Draw--- Copyright   :  (c) Stephen Tetley 2010--- License     :  BSD3------ Maintainer  :  stephen.tetley@gmail.com--- Stability   :  unstable--- Portability :  GHC------ Drawing the tree using Wumpus-Basic.--------------------------------------------------------------------------------------module Wumpus.Tree.Draw -  (-    drawTree-  , drawFamilyTree--  ) where--import Wumpus.Tree.Base-import Wumpus.Tree.TreeBuildMonad--import Wumpus.Basic.Kernel                      -- package: wumpus-basic-import Wumpus.Drawing.Dots.AnchorDots--import Wumpus.Core                              -- package: wumpus-core---import Control.Monad-import qualified Data.IntMap as IntMap-import Data.Tree hiding ( drawTree )-----drawTree :: (Real u, Floating u, InterpretUnit u) -          => NodeAnnoRefs u -> CoordTree u (TreeNodeAns u) -> TreeDrawing u-drawTree annos tree = drawStep annos radialConns tree >> return ()----drawFamilyTree :: (Real u, Floating u, InterpretUnit u) -          => NodeAnnoRefs u -> CoordTree u (TreeNodeAns u) -> TreeDrawing u-drawFamilyTree annos tree = drawStep annos familyConn tree >> return ()---drawStep :: (Real u, Floating u) -         => NodeAnnoRefs u -         -> (DotAnchor u -> [DotAnchor u] -> Graphic u)-         -> CoordTree u (TreeNodeAns u) -> TraceDrawing u (DotAnchor u)-drawStep annos connF (Node (pt,(fn, mb_ix)) ns) = do -    ancr <- drawi $ fn `at` pt-    xs   <- mapM (drawStep annos connF) ns   -    when (not $ null xs) $ draw $ connF ancr xs-    drawAnno annos ancr mb_ix-    return ancr--drawAnno :: NodeAnnoRefs u -> DotAnchor u -> Maybe Int -> TraceDrawing u ()-drawAnno _    _    Nothing   = return ()-drawAnno refs ancr (Just ix) = maybe (return ()) sk $ IntMap.lookup ix refs-  where-    sk fn = draw $ fn ancr----radialConns :: ( Real u, Floating u, InterpretUnit u-               , CenterAnchor a, RadialAnchor a -               , u ~ DUnit a) -            => a -> [a] -> Graphic u-radialConns a []     = emptyLocGraphic `at` (center a)-radialConns a (x:xs) = oconcat (connector a x) (map (connector a) xs)----connector :: ( Real u, Floating u, InterpretUnit u-             , CenterAnchor a, RadialAnchor a-             , u ~ DUnit a )  -          => a -> a -> Graphic u-connector a0 a1 = vertexPP [pt0,pt1] >>= openStroke-  where-    (ang0,ang1) = anchorAngles (center a0) (center a1)-    pt0         = radialAnchor ang0 a0-    pt1         = radialAnchor ang1 a1-    -----anchorAngles :: (Real u, Floating u) -             => Point2 u -> Point2 u -> (Radian,Radian)-anchorAngles f t = (theta0, theta1)-  where-    conn_v  = pvec f t-    theta0  = vdirection conn_v-    theta1  = if theta0 < pi then theta0 + pi else theta0 - pi-    ----------------------------------------------------------------------------------------- --familyConn :: ( Real u, Fractional u, InterpretUnit u-              , CenterAnchor a, CardinalAnchor a -              , u ~ DUnit a ) -           => a -> [a] -> Graphic u-familyConn a [] = emptyLocGraphic `at` (center a)-familyConn a xs = famconn (south a) (map north xs)--famconn :: (Fractional u, Ord u, InterpretUnit u) -        => Point2 u -> [Point2 u] -> Graphic u-famconn _       []         = error "famconn - empty list"-famconn pt_from [p1]       = famconn1 pt_from p1-famconn pt_from xs@(p1:_)  = oconcat downtick (horizontal : upticks)-   where-     hh         = halfHeight pt_from p1-     downtick   = locStraightLine (vvec (-hh)) `at` pt_from-     horizontal = midline (displaceV (-hh) pt_from) xs -     upticks    = map (locStraightLine (vvec hh) `at`) xs--midline :: (Fractional u, Ord u, InterpretUnit u) -        => Point2 u -> [Point2 u] -> Graphic u-midline _        []           = error "midline - empty list" -midline (P2 _ y) (P2 x0 _:zs) = -    let (a,b) = foldr fn (x0,x0) zs in straightLine (P2 a y) (P2 b y)-  where   -    fn (P2 x _) (lo,hi) | x < lo    = (x,hi)-                        | x > hi    = (lo,x)-                        | otherwise = (lo,hi)--halfHeight :: Fractional u => Point2 u -> Point2 u -> u-halfHeight (P2 _ ya) (P2 _ yb) = 0.5 * (abs $ ya - yb)- --- special case - should always be a vertical, but...----famconn1 :: (Fractional u, InterpretUnit u)-         => Point2 u -> Point2 u -> Graphic u-famconn1 a@(P2 xa _) b@(P2 xb _) -    | xa == xb  = straightLine a b-    | otherwise = vertexPP [a,m1,m2,b] >>= openStroke-  where-    hh = halfHeight a b-    m1 = displaceV (-hh)     a  -    m2 = displaceH (xb - xa) m1
+ src/Wumpus/Tree/DrawLoc.hs view
@@ -0,0 +1,112 @@+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module      :  Wumpus.Tree.DrawLoc+-- Copyright   :  (c) Stephen Tetley 2011+-- License     :  BSD3+--+-- Maintainer  :  stephen.tetley@gmail.com+-- Stability   :  unstable+-- Portability :  GHC+--+-- Drawing a Tree as a LocGraphic.+--+--------------------------------------------------------------------------------++module Wumpus.Tree.DrawLoc+  (+    +    runTreeLoc++  ) where++import Wumpus.Tree.Base+import Wumpus.Tree.Design+++import Wumpus.Basic.Kernel                      -- package: wumpus-basic++import Wumpus.Core                              -- package: wumpus-core++import Data.Tree hiding ( drawTree )+++--+-- DESIGN NOTE +--+-- Only simplistic trees can be drawn as LocGraphics.+--+-- Technically, this is because LocImages only support +-- /production/ of /answers/ and not their /introspection/, so+-- we cannot query anchors directly[*] during construction. Thus +-- we can\'t have /graph-links/ which need /located/ anchors.+--+-- [*] Though we can use @dblelaborate@ for a special case.+--+++-- | Build a LocGraphic from a @Data.Tree@.+--+-- Nodes support custom drawing as the value of the /label/ at +-- each node is interpreted (naturally, all node drawings must +-- be of the same type). +--+runTreeLoc :: (Real u, Floating u, InterpretUnit u) +           => TreeProps u a -> (elt -> LocImage u a) -> Tree elt +           -> LocGraphic u+runTreeLoc props drawF tree = promoteLoc $ \pt ->+    let tree1 = fmap drawF tree+    in zapQuery (runDesign props tree1) >>= \ans -> +       ignoreAns (drawStep props ans `at` pt)++++drawStep :: (Real u, Floating u, InterpretUnit u) +         => TreeProps u a -> Tree (LocImage u a) -> LocImage u a+drawStep props (Node gf ns) =+    getTreeConnector props >>= \conn ->+    let imgs = sequence $ map (drawStep props) ns+    in dblelaborate gf imgs conn+      ++-- | This is not really a generally function - the types are not+-- complementary and it returns only the first answer but consumes +-- the second, so it doesn\'t belong in Wumpus-Basic. +-- +-- However, it is a problematic that it needs to +-- deconstruct the Ans directly - this suggests there is a need +-- for a more general version of this combinator in Wumpus-Basic.+-- +dblelaborate :: LocImage u a -> LocImage u b +             -> (a -> b -> Graphic u) +             -> LocImage u a+dblelaborate ma mb fn = promoteLoc $ \pt -> +    both (ma `at` pt) (mb `at` pt) >>= \(a,b) -> fn a b >> return a++designOrientateScale :: (Real u, Floating u, InterpretUnit u)+                     => TreeProps u a  -> Tree (LocImage u a) +                     -> Query u (Tree (Point2 u, LocImage u a))+designOrientateScale props tree =  +    scaleTree sx sy (design tree) >>= \ans -> return $ orientateTree dir ans+  where+    dir = tp_direction props+    sx  = tp_sibling_distance props+    sy  = tp_level_distance props++++-- | Transform a tree where each node is a LocImage into a tree+-- where each LocImage is displaced by the necessary coordinate+-- so it can be drawn.+--+runDesign :: (Real u, Floating u, InterpretUnit u)+          => TreeProps u a  -> Tree (LocImage u a) +          -> Query u (Tree (LocImage u a))+runDesign props tree =  +    designOrientateScale props tree >>= \tree2 -> +    return $ fmap fn tree2+  where+    fn ((P2 x y), gf) = moveStart (vec x y) gf++
+ src/Wumpus/Tree/OTMConnectors.hs view
@@ -0,0 +1,173 @@+{-# LANGUAGE TypeFamilies               #-}+{-# LANGUAGE FlexibleContexts           #-}+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module      :  Wumpus.Tree.Draw+-- Copyright   :  (c) Stephen Tetley 2011+-- License     :  BSD3+--+-- Maintainer  :  stephen.tetley@gmail.com+-- Stability   :  unstable+-- Portability :  GHC+--+-- One-to-many connectors.+--+--------------------------------------------------------------------------------++module Wumpus.Tree.OTMConnectors+  (++    radialOTMC+  , blankOTMC+  , familyOTMC+  , splayOTMC++  ) where++import Wumpus.Tree.Base++import Wumpus.Drawing.Paths.Absolute            -- package: wumpus-drawing++import Wumpus.Basic.Kernel                      -- package: wumpus-basic++import Wumpus.Core                              -- package: wumpus-core++import Data.AffineSpace                         -- package: vector-space++import Data.Monoid++++++-- Pulling out the points (nodes) from parent plus list of +-- children.+++radialNodes :: ( Real u, Floating u, InterpretUnit u+               , CenterAnchor a, RadialAnchor a+               , u ~ DUnit a )  +            => a -> [a] -> [(Point2 u, Point2 u)]+radialNodes a as = map fn as+  where+    actr = center a+    fn x = (radialAnchor ang0 a , radialAnchor ang1 x) +             where (ang0, ang1) = anchorAngles actr (center x)+        ++anchorAngles :: (Real u, Floating u) +             => Point2 u -> Point2 u -> (Radian,Radian)+anchorAngles f t = (theta0, theta1)+  where+    conn_v  = pvec f t+    theta0  = vdirection conn_v+    theta1  = if theta0 < pi then theta0 + pi else theta0 - pi+++-- +-- @radialConn@ cannot be represented as a connector from+-- one-point-to-many-points as the initial points all start from+-- slightly different places. +--+++-- | 'radialOTMC' has no need for the TreeDirection or height step.+-- +radialOTMC :: ( Real u, Floating u, InterpretUnit u+              , CenterAnchor a, RadialAnchor a +              , u ~ DUnit a) +           => OTMAnchorConn u a+radialOTMC _ _ a xs = mconcat $ map fn $ radialNodes a xs+  where+    fn (p0,p1) = zapQuery (vertexPP [p0,p1]) >>= dcOpenPath++-- | Blank connector - nothing is drawn.+--+blankOTMC :: ( Real u, Floating u, InterpretUnit u+            , CenterAnchor a+            , u ~ DUnit a) +         => OTMAnchorConn u a+blankOTMC _ _ a _ = emptyLocImage `at` center a+++--------------------------------------------------------------------------------+-- ++-- Note - can the \"crossbar\" of a famillyConn cannot be +-- calcuated parent-to-arbitrary-child?+-- +-- Probably we need to know half the height step, rather than +-- calculate it from anchors.+--++-- Drawing a fmaily connector is quite horrible...++++familyOTMC :: ( Real u, Floating u, Ord u, Tolerance u, InterpretUnit u+              , CenterAnchor a, CardinalAnchor a +              , u ~ DUnit a ) +           => OTMAnchorConn u a+familyOTMC _   _ _ [] = mempty+familyOTMC dir h a xs = +    let hh        = 0.5 * h+        (paF,caF) = famAnchors dir+        ptick     = outtick hh (center a) (paF a)+        cticks    = map (\o -> outtick hh (center o) (caF o)) xs+        kids      = sequence cticks+    in ignoreAns ptick `mappend` (ignoreAns $ elaborate kids fn)+  where+    fn ps = case linkAll ps of+              Nothing -> emptyLocImage `at` (center a)+              Just path -> zapQuery (toPrimPath path) >>= dcOpenPath++++famAnchors :: (CardinalAnchor a, u ~ DUnit a ) +             => TreeDirection -> (a -> Anchor u, a -> Anchor u)+famAnchors TREE_UP    = (north, south)+famAnchors TREE_DOWN  = (south, north)+famAnchors TREE_LEFT  = (west,  east)+famAnchors TREE_RIGHT = (east,  west)++++outtick :: (Real u, Floating u, InterpretUnit u) +        => u -> Point2 u -> Point2 u -> Image u (Point2 u)+outtick ll p0 p1 = +    let v0  = pvec p0 p1+        ang = vdirection v0+        v1  = avec ang ll+        p2  = p0 .+^ v1+    in replaceAns p2 (straightLine p1 p2)++-- | The input list is expected to be ordered...+--+linkAll :: (Real u, Floating u, Ord u, Tolerance u) +        => [Point2 u] -> Maybe (AbsPath u)+linkAll [] = Nothing+linkAll xs = Just $ optimizeLines $ vertexPath xs++++++splayOTMC :: ( Real u, Floating u, Ord u, Tolerance u, InterpretUnit u+              , CenterAnchor a, CardinalAnchor a +              , u ~ DUnit a ) +           => OTMAnchorConn u a+splayOTMC _   _ _ [] = mempty+splayOTMC dir _ a xs = +    let (paF,caF) = famAnchors dir+        p0        = paF a+    in mconcat $ map (\x -> fn p0 (caF x)) xs+  where+    fn p0 p1 = zapQuery (vertexPP [p0,p1]) >>= dcOpenPath++++--------------------------------------------------------------------------------++
− src/Wumpus/Tree/ScalingContext.hs
@@ -1,103 +0,0 @@-{-# OPTIONS -Wall #-}------------------------------------------------------------------------------------- |--- Module      :  Wumpus.Tree.ScalingContext--- Copyright   :  (c) Stephen Tetley 2010-2011--- License     :  BSD3------ Maintainer  :  stephen.tetley@gmail.com--- Stability   :  unstable--- Portability :  GHC------ Scaling in X and Y------ \*\* WARNING \*\* - to be removed at some point.--- -----------------------------------------------------------------------------------module Wumpus.Tree.ScalingContext-  (--    ScalingContext(..)--  , scaleX-  , scaleY-  , scalePt-  , scaleVec--  , unitX-  , unitY--  , uniformScaling-  , coordinateScaling--  ) where---import Wumpus.Core				-- package: wumpus-core------ | ScalingContext is a dictionary of two functions for scaling --- in X and Y.----data ScalingContext ux uy u = ScalingContext-      { scale_in_x  :: ux -> u-      , scale_in_y  :: uy -> u-      }---scaleX              :: ScalingContext ux uy u -> ux -> u-scaleX ctx ux       = (scale_in_x ctx) ux--scaleY              :: ScalingContext ux uy u -> uy -> u-scaleY ctx uy       = (scale_in_y ctx) uy---scalePt             :: ScalingContext ux uy u -> ux -> uy -> Point2 u-scalePt ctx ux uy   = P2 (scale_in_x ctx ux) (scale_in_y ctx uy)--scaleVec            :: ScalingContext ux uy u -> ux -> uy -> Vec2 u-scaleVec ctx ux uy  = V2 (scale_in_x ctx ux) (scale_in_y ctx uy)---unitX               :: Num ux => ScalingContext ux uy u -> u-unitX ctx           = scaleX ctx 1- -unitY               :: Num uy => ScalingContext ux uy u -> u-unitY ctx           = scaleY ctx 1---------------------------------------------------------------------------------------- constructors for scaling context----- | Build a ScalingContext where both X and Y are scaled by the --- same uniform step.------ The dimensions (types) of the ScalingContext are unified - the --- output type and the input types are all the same.----uniformScaling :: Num u => u -> ScalingContext u u u-uniformScaling u = ScalingContext-      { scale_in_x  = (\x -> u*x)-      , scale_in_y  = (\y -> u*y)-      }------ | Build a ScalingContext for scaling Int coordinates.------ The scaling factors in X and Y can be different sizes.-----coordinateScaling :: Num u => u -> u -> ScalingContext Int Int u-coordinateScaling sx sy = ScalingContext-      { scale_in_x  = (\x -> sx * fromIntegral x)-      , scale_in_y  = (\y -> sy * fromIntegral y)-      }---
− src/Wumpus/Tree/TreeBuildMonad.hs
@@ -1,213 +0,0 @@-{-# LANGUAGE TypeFamilies               #-}-{-# OPTIONS -Wall #-}------------------------------------------------------------------------------------- |--- Module      :  Wumpus.Tree.TreeBuildMonad--- Copyright   :  (c) Stephen Tetley 2010-2011--- License     :  BSD3------ Maintainer  :  stephen.tetley@gmail.com--- Stability   :  unstable--- Portability :  GHC------ Build a tree within a monad - the monad allows anchor references.--------------------------------------------------------------------------------------module Wumpus.Tree.TreeBuildMonad-  (-    NodeId-  , ZNodeId-  , NodeAnno-  , NodeAnnoRefs-  -  , TreeBuild-  , TreeSpec-  , ZTreeSpec--  , TreeNodeAns-  , TreeBuildAns-  , runTreeBuild--  , regularBuild--  , nodeId-  , label--  , branch-  , zbranch-  , leaf-  , zleaf--  ) where--import Wumpus.Tree.Base--import Wumpus.Basic.Kernel                      -- package: wumpus-basic-import Wumpus.Drawing.Dots.AnchorDots---import Control.Applicative-import qualified Data.IntMap as IntMap-import Data.Monoid-import Data.Tree-------- | Nodes can be bound with @(>>=)@ or in the do-notation before --- they are drawn. This is similar to the concept of /embedded/ --- nodes in TikZ. Bound nodes can be referenced by their anchors --- e.g. to give them an extra annotation.------ This opaque type represents bound nodes and regular nodes that --- are just drawn and cannot be annotated.--- -data NodeId a = NodeId Int-              | RegularNode a-  deriving (Eq)---- The default node type. With this type, regular nodes have no--- payload so can only be drawn as some common graphic e.g. a --- filled or stroked disk.----type ZNodeId u = NodeId (UNil u)--type NodeDrawRefs u = IntMap.IntMap (TreeNode u)--type NodeAnno u     = DotAnchor u -> Graphic u--type NodeAnnoRefs u = IntMap.IntMap (NodeAnno u)--data St u = St-      { uid_counter     :: Int-      , node_refs       :: NodeDrawRefs u-      , anno_refs       :: NodeAnnoRefs u-      }---zeroSt :: St u-zeroSt = St { uid_counter = 0, node_refs = mempty, anno_refs = mempty }---newtype TreeBuild u a = TreeBuild { getTreeBuild :: St u -> (a, St u) }--instance Functor (TreeBuild u) where-  fmap f ma = TreeBuild $ \s -> let (a,s1) = getTreeBuild ma s in (f a, s1)--instance Applicative (TreeBuild u) where-  pure a    = TreeBuild $ \s -> (a,s)-  mf <*> ma = TreeBuild $ \s -> let (f,s1) = getTreeBuild mf s-                                    (a,s2) = getTreeBuild ma s1-                                in (f a,s2)--instance Monad (TreeBuild u) where-  return a  = TreeBuild $ \s -> (a,s)-  ma >>= k  = TreeBuild $ \s -> let (a,s1) = getTreeBuild ma s -                                in getTreeBuild (k a) s1 ---type TreeSpec a   = Tree (NodeId a)-type ZTreeSpec u  = TreeSpec (UNil u)---type TreeNodeAns  u = (TreeNode u, Maybe Int)-type TreeBuildAns u = (Tree (TreeNodeAns u), NodeAnnoRefs u)---- | This is the @run@ function for the TreeBuild monad.------ Note the monadic /command/ is type specialized to --- @(TreeSpec a)@, this is because evaluation in the TreeBuild--- monad is only significant for producing a @Tree (TreeNode u)@.-----runTreeBuild :: (Real u, Floating u, InterpretUnit u)-             => (a -> TreeNode u) -> TreeBuild u (TreeSpec a) -> TreeBuildAns u-runTreeBuild regDrawF ma = -    let (a,s) = getTreeBuild ma zeroSt-        t1    = postRun regDrawF (a, node_refs s)-    in (t1, anno_refs s)----- As the constructor to build NodeIds is not exposed a --- TreeBuild should not be able to refer to uninstantiated--- nodes, however while the failure continuation should be --- unreachable we still need it in the code to make the --- IntMap.lookup total.----postRun :: (Real u, Floating u, InterpretUnit u)-        => (a -> TreeNode u) -> (TreeSpec a,NodeDrawRefs u) -        -> Tree (TreeNode u, Maybe Int)-postRun regDrawF (tree1,table) = fmap changeNode tree1-  where-    changeNode (RegularNode a)  = (regDrawF a, Nothing)-    changeNode (NodeId ix)      = maybe fk (sk ix) $ IntMap.lookup ix table -    -    sk ix                       = \a -> (a, Just ix)-    fk                          = (dotText "Error missing node", Nothing)- ----- | Turn an ordinary @Data.Tree@ into a /regular/ 'TreeSpec'.------ All nodes become /regular/ nodes, no nodes are /bound/. Thus--- nodes cannot be annotated etc.---  -regularBuild :: Tree a -> TreeBuild u (TreeSpec a)-regularBuild (Node a kids) =  -    Node (RegularNode a) <$> mapM regularBuild kids---nodeId :: TreeNode u -> TreeBuild u (NodeId a)-nodeId drawF = -    TreeBuild $ \(St ix nodes annos) -> -      let nodes' = IntMap.insert ix drawF nodes-      in (NodeId ix, St (ix+1) nodes' annos)---- | Note - this is not /in/ the TreeBuild monad.----label :: a -> NodeId a -label a = RegularNode a---{---- | Annotate a /node/ with a 'NodeAnno'.--- --- Note - /regular/ nodes cannot be annotated, a node must be --- bound to a variable first with 'nodeId'.------ Also this function is not so useful now Wumpus-Basic has--- the @decorate@, @sdecorate@, and @adecorate@ functions.--- -annotate :: u ~ DUnit a => NodeId a -> NodeAnno u -> TreeBuild u ()-annotate (RegularNode _) _     = return ()-annotate (NodeId nid)    annoF = -    TreeBuild $ \(St ix nodes annos) -> -      let annos' = IntMap.insert nid annoF annos-      in ((), St ix nodes annos')--}---branch :: NodeId a -> [TreeSpec a] -> TreeSpec a-branch uid kids = Node uid kids----- | Default /branch/ - has children.----zbranch :: [ZTreeSpec u] -> ZTreeSpec u-zbranch kids = Node (RegularNode UNil) kids --leaf :: NodeId a -> TreeSpec a-leaf uid = Node uid []---- | Default /leaf/ - tree node with no children.----zleaf :: ZTreeSpec u-zleaf = Node (RegularNode UNil) []---            --
+ src/Wumpus/Tree/TreeBuilder.hs view
@@ -0,0 +1,316 @@+{-# LANGUAGE TypeFamilies               #-}+{-# LANGUAGE FlexibleContexts           #-}+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module      :  Wumpus.Tree.TreeBuilder+-- Copyright   :  (c) Stephen Tetley 2011+-- License     :  BSD3+--+-- Maintainer  :  stephen.tetley@gmail.com+-- Stability   :  unstable+-- Portability :  GHC+--+-- Monadic building - trees with references for indirect +-- node-to-node connections and decoration+--+--------------------------------------------------------------------------------++module Wumpus.Tree.TreeBuilder+  (+    AbsTreeSpec+  , TreeSpec+  , TbNode++  , ref +  , leaf+  , root+  , mkleaf+  , linkref    ++  , drawTreeSpec++  ) where++import Wumpus.Tree.Base+import Wumpus.Tree.Design++import Wumpus.Drawing.Basis.TraceGraphic        -- package: wumpus-drawing++import Wumpus.Basic.Kernel                      -- package: wumpus-basic+import Wumpus.Basic.Utils.HList++import Wumpus.Core                              -- package: wumpus-core++import Control.Applicative+import qualified Data.IntMap as IM+import Data.Monoid+import Data.Tree++-- TODO - are you sure this needs to build a Graphic rather than +-- a LocGraphic?+++data TbNode u a = RefNode Int (LocImage u a)+                | PlainNode (LocImage u a)++type instance DUnit (TbNode u a) = u++++type RefTree u a = Tree (TbNode u a)++type CoordRefTree u a = Tree (Point2 u, TbNode u a)++++type LinkDraw u node  = (node -> node -> Graphic u)+++-- | This allows special connectors or edge labels.+--+type LinkRef u node = (Int,Int, LinkDraw u node)+++newtype TreeSpec node u a = TreeSpec { +          getTreeSpec :: Int -> (a, Int, H (LinkRef u node)) }++type instance MonUnit (TreeSpec node u a) = u+++type AbsTreeSpec u node = TreeSpec node u (RefTree u node)+++-- Functor++instance Functor (TreeSpec node u) where+  fmap f ma = TreeSpec $ \s0 -> let (a,s1,w1) = getTreeSpec ma s0 +                                in (f a, s1, w1)+++-- Applicative++instance Applicative (TreeSpec node u) where+  pure a    = TreeSpec $ \s0  -> (a, s0, mempty)+  mf <*> ma = TreeSpec $ \s0 -> +                let (f,s1,w1) = getTreeSpec mf s0+                    (a,s2,w2) = getTreeSpec ma s1+                in (f a, s2, w1 `mappend` w2)+++-- Monad++instance Monad (TreeSpec node u) where+  return a = TreeSpec $ \s0 -> (a, s0, mempty)+  ma >>= k = TreeSpec $ \s0 -> let (a,s1,w1) = getTreeSpec ma s0+                                   (b,s2,w2) = (getTreeSpec . k) a s1+                               in (b,s2, w1 `mappend` w2)+++runTreeSpec :: AbsTreeSpec u node -> (RefTree u node, [LinkRef u node])+runTreeSpec ma = let (a,_,w1) = getTreeSpec ma 0 +                 in (a, toListH w1)+++ref :: LocImage u node -> TreeSpec node u (TbNode u node)+ref img = TreeSpec $ \s0 -> (RefNode s0 img, s0+1, mempty)++leaf :: TbNode u node -> RefTree u node +leaf nod = Node nod []++root :: TbNode u node -> [RefTree u node ] -> RefTree u node +root n1 xs = Node n1 xs++mkleaf :: LocImage u node -> RefTree u node+mkleaf img = Node (PlainNode img) []+++linkref :: TbNode u node -> TbNode u node -> LinkDraw u node -> TreeSpec node u ()+linkref (RefNode ix _) (RefNode jx _) fn = TreeSpec $ \s0 -> +   ((), s0, wrapH $ (ix,jx, fn))++linkref _              _              _  = TreeSpec $ \s0 -> ((), s0, mempty)++++-------------------------------------------------------------+-- +++++-- | Map for indexed objects that support taking anchors.+--+type ObjectMap node = IM.IntMap node++++drawTreeSpec :: ( Real u, Floating u, InterpretUnit u+                , DrawingCtxM m, TraceM m, u ~ MonUnit (m ())+                )+             => TreeProps u node -> Point2 u +             -> AbsTreeSpec u node+             -> m ()+drawTreeSpec props rootpt ma = +    let (rtree,links) = runTreeSpec ma+    in  makeCoordRefTree props rootpt rtree >>= \ctree -> +        askDC >>= \ctx ->+        let prim = rawBuildPrim ctx props ctree links+        in trace prim ++makeCoordRefTree :: ( Real u, Floating u, InterpretUnit u+                    , DrawingCtxM m, u ~ MonUnit (m ())+                    )+                 => TreeProps u a -> Point2 u -> RefTree u a +                 -> m (CoordRefTree u a)+makeCoordRefTree props (P2 x y) tree = +    scaleTree sx sy (design tree) >>= \ans -> return $ moveTree $ orient ans+  where+    orient   = orientateTree (tp_direction props)+    moveTree = fmap (bimapL (displace $ V2 x y))+    sx       = tp_sibling_distance props+    sy       = tp_level_distance props+++-- Whoa - have to be very careful about producing something that +-- is consistent with the DrawingContext.+-- +-- If we fork the DrawingContext we don\'t want to produce a +-- Graphic as a Graphic should be able to be (re-)drawn various +-- times in updated Contexts and reflect the changes each time.+--+-- Need a custom draw function... ++++rawBuildPrim :: InterpretUnit u +             => DrawingContext -> TreeProps u node +             -> CoordRefTree u node+             -> [LinkRef u node]+             -> HPrim u+rawBuildPrim ctx props tree links = +    let (_,w1,o) = runBuilder ctx props (node1 tree) +        w2       = foldr (fn o) mempty links+    in w1 `mappend` w2+  where+    fn imap (i,j,drawF) acc = case (IM.lookup i imap, IM.lookup j imap) of+        (Just a, Just b) -> let (PrimW o _) = runImage ctx (drawF a b)+                            in singleH o `mappend` acc+        _                -> acc+++node1 :: InterpretUnit u+      => CoordRefTree u node -> Builder node u node+node1 (Node (pt, RefNode ix gf) kids) = +    let img = applyLoc gf pt+    in do { a <- tellImage img+          ; addNodeRef ix a+          ; as <- mapM node1 kids+          ; conn <- currentConnector+          ; tellImage_ (conn a as)+          ; return a+          }++node1 (Node (pt, PlainNode gf) kids) = +    let img = applyLoc gf pt+    in do { a <- tellImage img+          ; as <- mapM node1 kids+          ; conn <- currentConnector+          ; tellImage_ (conn a as)+          ; return a+          }+++--------------------------------------------------------------------------------+-- Here a dependency on MTL would be useful...++newtype MonBase node u a = MonBase { +    getMonBase :: TreeProps u node -> ObjectMap node -> (a, ObjectMap node) }++newtype Builder node u a = Builder { +    getBuilder :: TraceGraphicT u (MonBase node u) a } ++type instance MonUnit (MonBase node u a) = u+type instance MonUnit (Builder node u a) = u+++-- Functor++instance Functor (MonBase node u) where+  fmap f ma = MonBase $ \env s0 -> let (a,s1) = getMonBase ma env s0 +                                   in (f a, s1)++instance Functor (Builder node u) where+  fmap f = Builder . fmap f . getBuilder +++-- Applicative++instance Applicative (MonBase node u) where+  pure a    = MonBase $ \_   s0  -> (a, s0)+  mf <*> ma = MonBase $ \env s0 -> +                let (f,s1) = getMonBase mf env s0+                    (a,s2) = getMonBase ma env s1+                in (f a, s2)++instance Applicative (Builder node u) where+  pure a    = Builder $ pure a+  mf <*> ma = Builder $ getBuilder mf <*> getBuilder ma +++-- Monad++instance Monad (MonBase node u) where+  return a = MonBase $ \_   s0 -> (a, s0)+  ma >>= k = MonBase $ \env s0 -> let (a,s1) = getMonBase ma env s0+                                   in (getMonBase . k) a env s1+++instance Monad (Builder node u) where+  return a = Builder $ return a+  ma >>= f = Builder $ getBuilder ma >>= getBuilder . f+++-- TraceGraphicM++instance TraceGraphicM (Builder node u) where+  tellImage img = Builder $ tellImage img+++-- DrawingCtxM++instance DrawingCtxM (Builder node u) where+  askDC           = Builder $ askDC+  asksDC f        = Builder $ asksDC f+  localize upd ma = Builder $ localize upd (getBuilder ma)++++liftBSt :: MonBase node u a -> Builder node u a+liftBSt ma = Builder $ liftTraceGraphicT ma++addNodeRef :: Int -> node -> Builder node u ()+addNodeRef i a = liftBSt inside+  where+    inside = MonBase $ \_ s0 -> ((), IM.insert i a s0)+++currentConnector :: InterpretUnit u +                 => Builder node u (node -> [node] -> Graphic u)+currentConnector = liftBSt inside >>= getTreeConnector+  where+    inside = MonBase $ \env s0 -> (env,s0)+++runMonBase :: TreeProps u node -> MonBase node u a -> (a, ObjectMap node)+runMonBase props ma = getMonBase ma props mempty+++runBuilder :: DrawingContext +           -> TreeProps u node +           -> (Builder node u a) +           -> (a, HPrim u, ObjectMap node)+runBuilder ctx props ma = +    let ((a,wp),s) = runMonBase props (runTraceGraphicT ctx (getBuilder ma)) in (a,wp,s)+
src/Wumpus/Tree/VersionNumber.hs view
@@ -22,7 +22,7 @@  -- | Version number ----- > (0,15,0)+-- > (0,16,0) -- wumpus_tree_version :: (Int,Int,Int)-wumpus_tree_version = (0,15,0)+wumpus_tree_version = (0,16,0)
wumpus-tree.cabal view
@@ -1,5 +1,5 @@ name:             wumpus-tree-version:          0.15.0+version:          0.16.0 license:          BSD3 license-file:     LICENSE copyright:        Stephen Tetley <stephen.tetley@gmail.com>@@ -32,48 +32,15 @@   .   Changelog:   .-  v0.14.0 to v0.15.0-  .-  * Updated to work with latest Wumpus libraries. -    @ScalingContext@ has been temporarily added from Wumpus-Basic -    (it was considered obsolete there). At some point the -    functionality needs re-implementing so it can be removed from -    Tree.-  .  -  v0.13.0 to v0.14.0:-  .-  * Updated to work with latest Wumpus libraries. -  .-  v0.12.0 to v0.13.0:-  .-  * Changed the specification of trees so that they are built in a-    monad. The bind operation of the monad allows /anchors/ to be -    extracted from tree nodes so they can be annotated with -    supplementary graphics. At the moment this is rather limited -    as Wumpus-Basic and Wumpus-Drawing do not offer much support -    for anchors other than the basic type classes.-  .-  * Changed the type of the rendering functions so they produce a -    TreeDrawing. This type is more suitable for building composite-    pictures than the previous type TreePicture. -  .-  * Also the rendering functions now take a start point for the -    root node, again this should be more convenient for drawing -    composite pictures - see the demo which now draws all the -    example trees on one page.-  .-  * Internally the tree design is now more flexible - trees can be -    designed upwards or leftwards rightwards, rather than just -    downwards; and edge drawing style is lifted out of the -    rendering to use a supplied combinator. Currently these -    features are not exposed by the API, the API needs more -    thought (possibly warranting changes to Wumpus-Basic and -    Wumpus-Drawing).+  v0.15.0 to v0.16.0:   .+  * Re-worked so tree drawings form a @LocGraphic@ rather than a +    @TraceDrawing@, this makes more in line with other graphic +    objects in Wumpus like shapes.   .-  v0.11.1 to v0.12.0:+  * Changed node type to be any @LocImage@ where the answer +    supports anchors.   .-  * Internal changes to track updates to Wumpus-Basic.   .    . build-type:         Simple@@ -90,18 +57,18 @@   build-depends:      base              <  5,                        containers        >= 0.3.0     && <= 0.6.0,                       vector-space      >= 0.6       && <  1.0,-                      wumpus-core       >= 0.50.0    && <  0.51.0,-                      wumpus-basic      == 0.17.0,-                      wumpus-drawing    == 0.3.0+                      wumpus-core       >= 0.51.0    && <  0.52.0,+                      wumpus-basic      == 0.18.0,+                      wumpus-drawing    == 0.4.0       exposed-modules:     Wumpus.Tree,     Wumpus.Tree.Base,     Wumpus.Tree.Design,-    Wumpus.Tree.Draw,-    Wumpus.Tree.ScalingContext,-    Wumpus.Tree.TreeBuildMonad,+    Wumpus.Tree.DrawLoc,+    Wumpus.Tree.OTMConnectors,+    Wumpus.Tree.TreeBuilder,     Wumpus.Tree.VersionNumber    other-modules: