{-# OPTIONS -Wall #-} -------------------------------------------------------------------------------- -- | -- Module : Wumpus.Tree -- Copyright : (c) Stephen Tetley 2010 -- License : BSD3 -- -- Maintainer : Stephen Tetley -- Stability : highly unstable -- Portability : GHC -- -------------------------------------------------------------------------------- module Wumpus.Tree ( -- * The type of rendered trees TreePicture -- * Render a Data.Tree to a TreePicture , DrawingAttr(..) -- re-export , standardAttr -- re-export , ScaleFactors(..) , uniformScaling , drawTreePicture -- * Output to file , writeEPS_TreePicture , writeSVG_TreePicture -- * Drawing nodes , charNode , textNode , circleNode , diskNode ) where import Wumpus.Tree.Base import Wumpus.Tree.Design import Wumpus.Tree.Draw import Wumpus.Basic.Dots -- package: wumpus-basic import Wumpus.Basic.Graphic import Wumpus.Basic.Graphic.DrawingAttr import Wumpus.Basic.Monads.Drawing import Wumpus.Core -- package: wumpus-core import Data.Maybe import Data.Tree hiding ( drawTree ) -- | Output a 'TreePicture', generating an EPS file. -- writeEPS_TreePicture :: FilePath -> TreePicture -> IO () writeEPS_TreePicture = writeEPS_latin1 -- | Output a 'TreePicture', generating a SVG file. -- writeSVG_TreePicture :: FilePath -> TreePicture -> IO () writeSVG_TreePicture = writeSVG_latin1 -- | 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. -- data ScaleFactors = ScaleFactors { dx_scale :: Double , dy_scale :: Double } deriving (Eq,Show) -- | Build uniform x- and y-scaling factors, i.e. @ x == y @. -- uniformScaling :: Double -> ScaleFactors uniformScaling u = ScaleFactors u u -- | 'drawTreePicture' : @ draw_fun * attr * scale_factors * tree -> TreePicture @ -- -- The rendering function. -- -- @draw_fun@ renders the individual nodes. Usually 'charNode', -- 'circleNode' -- -- @attr@ is the font size (translates to node size), stroke -- colour, fill colour. -- -- @scale_factors@ scales the distances between parent and child -- (y-scale) and sibling nodes (x-scale). -- -- @tree@ is the input tree to be rendered. -- -- drawTreePicture :: (a -> TreeNode) -> DrawingAttr -> ScaleFactors -> Tree a -> TreePicture drawTreePicture drawF attr sfactors tree = fromMaybe errK $ drawGraphic $ drawTree drawF attr $ design funs tree where funs = scalingFunctions sfactors errK :: a errK = error "treePicture - empty tree drawing." scalingFunctions :: ScaleFactors -> (Double -> Double, Int -> Double) scalingFunctions (ScaleFactors sx sy) = (fx,fy) where fx d = sx * d fy d = sy * fromIntegral d -------------------------------------------------------------------------------- -- Drawing functions -- | Render tree nodes with a single character. -- -- Useful for rendering @ Data.Tree Char @. -- charNode :: Char -> TreeNode 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 :: String -> TreeNode 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 :: RGBi -> (a -> TreeNode) circleNode rgb = const fn where fn = dotCircle `props` (\s -> s { stroke_colour = rgb}) -- | Tree nodes with a filled circle. -- -- Suitable for printing the shape of a tree, ignoring the data. -- diskNode :: RGBi -> (a -> TreeNode) diskNode rgb = const fn where fn = dotDisk `props` (\s -> s { fill_colour = rgb})