module Graphics.Rendering.Chart.Legend(
Legend(..),
LegendStyle(..),
LegendOrientation(..),
legendToRenderable,
legend_label_style,
legend_margin,
legend_plot_size,
legend_orientation
) where
import Data.List (partition,intersperse)
import Control.Lens
import Data.Default.Class
import Graphics.Rendering.Chart.Geometry
import Graphics.Rendering.Chart.Drawing
import Graphics.Rendering.Chart.Renderable
import Graphics.Rendering.Chart.Grid
data LegendStyle = LegendStyle {
_legend_label_style :: FontStyle,
_legend_margin :: Double,
_legend_plot_size :: Double,
_legend_orientation :: LegendOrientation
}
data LegendOrientation = LORows Int
| LOCols Int
data Legend x y = Legend LegendStyle [(String, Rect -> BackendProgram ())]
instance ToRenderable (Legend x y) where
toRenderable = setPickFn nullPickFn . legendToRenderable
legendToRenderable :: Legend x y -> Renderable String
legendToRenderable (Legend ls lvs) = gridToRenderable grid
where
grid :: Grid (Renderable String)
grid = case _legend_orientation ls of
LORows n -> mkGrid n aboveG besideG
LOCols n -> mkGrid n besideG aboveG
aboveG, besideG :: [Grid (Renderable String)] -> Grid (Renderable String)
aboveG = aboveN.intersperse ggap1
besideG = besideN.intersperse ggap1
mkGrid :: Int
-> ([Grid (Renderable String)] -> Grid (Renderable String))
-> ([Grid (Renderable String)] -> Grid (Renderable String))
-> Grid (Renderable String)
mkGrid n join1 join2 = join1 [ join2 (map rf ps1) | ps1 <- groups n ps ]
ps :: [(String, [Rect -> BackendProgram ()])]
ps = join_nub lvs
rf :: (String, [Rect -> BackendProgram ()]) -> Grid (Renderable String)
rf (title,rfs) = besideN [gpic,ggap2,gtitle]
where
gpic :: Grid (Renderable String)
gpic = besideN $ intersperse ggap2 (map rp rfs)
gtitle :: Grid (Renderable String)
gtitle = tval $ lbl title
rp :: (Rect -> BackendProgram ()) -> Grid (Renderable String)
rp rfn = tval Renderable {
minsize = return (_legend_plot_size ls, 0),
render = \(w,h) -> do
_ <- rfn (Rect (Point 0 0) (Point w h))
return (\_-> Just title)
}
ggap1, ggap2 :: Grid (Renderable String)
ggap1 = tval $ spacer (_legend_margin ls,_legend_margin ls / 2)
ggap2 = tval $ spacer1 (lbl "X")
lbl :: String -> Renderable String
lbl = label (_legend_label_style ls) HTA_Left VTA_Centre
groups :: Int -> [a] -> [[a]]
groups _ [] = []
groups n vs = let (vs1,vs2) = splitAt n vs in vs1:groups n vs2
join_nub :: [(String, a)] -> [(String, [a])]
join_nub ((x,a1):ys) = case partition ((==x) . fst) ys of
(xs, rest) -> (x, a1:map snd xs) : join_nub rest
join_nub [] = []
instance Default LegendStyle where
def = LegendStyle
{ _legend_label_style = def
, _legend_margin = 20
, _legend_plot_size = 20
, _legend_orientation = LORows 4
}
$( makeLenses ''LegendStyle )