cpsa-2.0.0: src/CPSA/Graph/CompactView.hs
-- Generates a compact view of CPSA S-expressions as an SVG image
-- Copyright (c) 2009 The MITRE Corporation
--
-- This program is free software: you can redistribute it and/or
-- modify it under the terms of the BSD License as published by the
-- University of California.
module CPSA.Graph.CompactView (compactView) where
import System.IO
import CPSA.Graph.XMLOutput
import CPSA.Graph.Config
import CPSA.Graph.SVG
import CPSA.Graph.Loader
import CPSA.Graph.Tree
import CPSA.Graph.Preskeleton
compactView :: Handle -> Config -> [Preskel] -> IO ()
compactView h config preskels =
do
let (width, height, es) = draw config preskels
hPutStrLn h $ show $ docRoot config width height es
hClose h
return ()
-- Generates the SVG document root.
docRoot :: Config -> Float -> Float -> [Element] -> Element
docRoot conf w h es =
ec "svg" attrs es
where
attrs = [("width", showL w ++ units conf),
("height", showL h ++ units conf),
("xmlns", "http://www.w3.org/2000/svg"),
("xmlns:xlink", "http://www.w3.org/1999/xlink"),
("version", "1.1"),
("viewBox", viewbox),
("font-size", showL (font conf)),
("onload", "init(evt)")]
viewbox = "0 0 " ++ showL w ++ " " ++ showL h
draw :: Config -> [Preskel] -> (Float, Float, [Element])
draw conf ks =
case forest ks of
[t] ->
(w, h, [script, defs conf, e])
where
(w, h, e) = tdraw conf 0 0 t
ts ->
fdraw conf ts
-- Draw a forest
fdraw :: Config -> Forest -> (Float, Float, [Element])
fdraw conf ts =
(w + fw, max h fh, script : defs conf : rect conf 0 0 w h : es)
where
w = 2 * mx conf
h = 2 * my conf + fromIntegral (length ts - 1) * ty conf
(fw, fh, es) = foldl f (0, 0, index conf ts) ts
f (fw, fh, es) t =
(max fw tw, max fh th, e : es)
where
(tw, th, e) = tdraw conf w 0 t
-- Draw an index that gives access to trees in the forest
index :: Config -> Forest -> [Element]
index conf (t:ts) =
snd $ foldl loop (y, top) ts
where
x = mx conf
y = my conf
top = [tbutton conf x y (label (vertex t))]
loop (y1, es) t =
(y2, es')
where
es' = tbutton conf x y2 (label (vertex t)) : es
y2 = y1 + ty conf
index _ _ = error "Tree: Empty forest found"
-- Draw one tree in the forest
tdraw :: Config -> Float -> Float -> Tree -> (Float, Float, Element)
tdraw conf x y t =
(w, h, ec "svg" attrs (rect conf 0 0 tw th : contents))
where
attrs = [("id", "t" ++ show (label (vertex t))),
("x", showL x), ("y", showL y),
("width", showL w), ("height", showL h),
("visibility", "hidden")]
w = tw + kw -- Total width
h = max th kh -- Total height
(tw, th, es) = tree conf t
(kw, kh, contents) = body conf tw 0 (0, 0, es) t
-- Extract the preskeletons within one tree
body :: Config -> Float -> Float -> (Float, Float, [Element]) ->
Tree -> (Float, Float, [Element])
body conf x y (w, h, es) t =
foldl (body conf x y) (max w w', max h h', e:es) (children t)
where
(w', h', e) = kdraw conf x y (vertex t)