module Graphics.Rendering.Chart.Legend(
Legend(..),
LegendStyle(..),
LegendOrientation(..),
defaultLegendStyle,
legendToRenderable,
legend_label_style,
legend_margin,
legend_plot_size,
legend_orientation
) where
import Control.Monad
import Data.List (nub, partition,intersperse)
import Control.Lens
import Data.Default.Class
import Graphics.Rendering.Chart.Geometry
import Graphics.Rendering.Chart.Drawing
import Graphics.Rendering.Chart.Plot.Types
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 -> ChartBackend ())]
instance ToRenderable (Legend x y) where
toRenderable = setPickFn nullPickFn . legendToRenderable
legendToRenderable :: Legend x y -> Renderable String
legendToRenderable (Legend ls lvs) = gridToRenderable grid
where
grid = case _legend_orientation ls of
LORows n -> mkGrid n aboveG besideG
LOCols n -> mkGrid n besideG aboveG
aboveG = aboveN.(intersperse ggap1)
besideG = besideN.(intersperse ggap1)
mkGrid n join1 join2 = join1 [ join2 (map rf ps1) | ps1 <- groups n ps ]
ps :: [(String, [Rect -> ChartBackend ()])]
ps = join_nub lvs
rf (title,rfs) = besideN [gpic,ggap2,gtitle]
where
gpic = besideN $ intersperse ggap2 (map rp rfs)
gtitle = tval $ lbl title
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 = tval $ spacer (_legend_margin ls,_legend_margin ls / 2)
ggap2 = tval $ spacer1 (lbl "X")
lbl s = label (_legend_label_style ls) HTA_Left VTA_Centre s
groups :: Int -> [a] -> [[a]]
groups n [] = []
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 [] = []
defaultLegendStyle :: LegendStyle
defaultLegendStyle = def
instance Default LegendStyle where
def = LegendStyle
{ _legend_label_style = def
, _legend_margin = 20
, _legend_plot_size = 20
, _legend_orientation = LORows 4
}
$( makeLenses ''LegendStyle )