packages feed

Chart 1.9.3 → 1.9.5

raw patch · 17 files changed

Files

Chart.cabal view
@@ -1,5 +1,5 @@ Name: Chart-Version: 1.9.3+Version: 1.9.5 License: BSD3 License-file: LICENSE Copyright: Tim Docker, 2006-2014@@ -14,19 +14,20 @@               Documentation: https://github.com/timbod7/haskell-chart/wiki. Category: Graphics-Cabal-Version: >= 1.6+Cabal-Version: 1.18 Build-Type: Simple  library+  default-language: Haskell98   Build-depends: base >= 3 && < 5                , old-locale-               , time, mtl, array-               , lens >= 3.9 && < 4.19+               , time, array+               , lens >= 3.9 && < 5.3                , colour >= 2.2.1 && < 2.4                , data-default-class < 0.2-               , mtl >= 2.0 && < 2.3+               , mtl >= 2.0 && < 2.4                , operational >= 0.2.2 && < 0.3-               , vector >=0.9 && <0.13+               , vector >=0.9 && <0.14    if !impl(ghc >= 8.0)     build-depends: semigroups >= 0.18.4 && <0.19
Graphics/Rendering/Chart/Axis/Floating.hs view
@@ -30,7 +30,7 @@     loga_labelf ) where -import Data.List(minimumBy)+import Data.List(minimumBy, nub) import Data.Ord (comparing) import Data.Default.Class import Numeric (showEFloat, showFFloat)@@ -68,7 +68,7 @@  -- | A wrapper class for doubles used to indicate they are to -- be plotted against a log axis.-newtype LogValue = LogValue Double+newtype LogValue = LogValue {unLogValue :: Double}     deriving (Eq, Ord, Num, Real, Fractional, RealFrac, Floating, RealFloat)  instance Show LogValue where@@ -142,7 +142,7 @@  showWithoutOffset :: RealFloat d => [d] -> [String] showWithoutOffset xs-  | useScientificNotation = map (\x -> showEFloat' (Just 1) x) xs+  | useScientificNotation = map (showEFloat' (Just 1)) xs   | otherwise = map showD xs   where     -- use scientific notation if max value is too big or too small@@ -186,7 +186,7 @@ }  instance (Show a, RealFloat a) => Default (LinearAxisParams a) where-  def = LinearAxisParams +  def = LinearAxisParams     { _la_labelf    = showDs     , _la_nLabels   = 5     , _la_nTicks    = 50@@ -249,16 +249,16 @@ ----------------------------------------------------------------------  instance (Show a, RealFloat a) => Default (LogAxisParams a) where-  def = LogAxisParams +  def = LogAxisParams     { _loga_labelf = showDs     } --- | Generate a log axis automatically, scaled appropriate for the+-- | Generate a log axis automatically, scaled appropriately for the -- input data. autoScaledLogAxis :: RealFloat a => LogAxisParams a -> AxisFn a autoScaledLogAxis lap ps0 =     makeAxis' (realToFrac . log) (realToFrac . exp)-              (_loga_labelf lap) (wrap rlabelvs, wrap rtickvs, wrap rgridvs)+              (_loga_labelf lap) (wrap rlabelvs, wrap rtickvs, wrap rlabelvs)         where           ps        = filter (\x -> isValidNumber x && 0 < x) ps0           (minV,maxV) = (minimum ps,maximum ps)@@ -266,7 +266,7 @@           range []  = (3,30)           range _   | minV == maxV = (realToFrac $ minV/3, realToFrac $ maxV*3)                     | otherwise    = (realToFrac $ minV,   realToFrac $ maxV)-          (rlabelvs, rtickvs, rgridvs) = logTicks (range ps)+          (rlabelvs, rtickvs) = logTicks (range ps)   data LogAxisParams a = LogAxisParams {@@ -276,13 +276,13 @@  {-  Rules: Do not subdivide between powers of 10 until all powers of 10-          get a major ticks.+          get major ticks.         Do not subdivide between powers of ten as [1,2,4,6,8,10] when-          5 gets a major ticks-          (ie the major ticks need to be a subset of the minor tick)+          5 gets a major tick+          (i.e. the major ticks need to be a subset of the minor ticks) -}-logTicks :: Range -> ([Rational],[Rational],[Rational])-logTicks (low,high) = (major,minor,major)+logTicks :: Range -> ([Rational],[Rational])+logTicks (low,high) = (nub major,nub minor)  where   pf :: RealFrac a => a -> (Integer, a)   pf = properFraction@@ -299,17 +299,17 @@                maximum (1:filter (\x -> log10 (fromRational x) <= r) l)*10^^i   upper a l  = let (i,r) = pf (log10 a) in                minimum (10:filter (\x -> r <= log10 (fromRational x)) l)*10^^i-               +   powers           :: (Double,Double) -> [Rational] -> [Rational]   powers (x,y) l    = [ a*10^^p | p <- [(floor (log10 x))..(ceiling (log10 y))] :: [Integer]                                 , a <- l ]   midselection r l  = filter (inRange r l) (powers r l)   inRange (a,b) l x = (lower a l <= x) && (x <= upper b l)-  +   logRange = (log10 low, log10 high)-  +   roundPow x = 10^^(round x :: Integer)-  +   major | 17.5 < log10 ratio = map roundPow $                                steps (min 5 (log10 ratio)) logRange         | 12 < log10 ratio   = map roundPow $@@ -326,19 +326,15 @@   (dl',dh') = (fromRational l', fromRational h')   ratio' :: Double   ratio' = fromRational (h'/l')-  filterX = filter (\x -> l'<=x && x <=h') . powers (dl',dh') -  +  filterX = filter (\x -> l'<=x && x <=h') . powers (dl',dh')+   minor | 50 < log10 ratio' = map roundPow $                               steps 50 (log10 dl', log10 dh')         | 6 < log10 ratio'  = filterX [1,10]-        | 3 < log10 ratio'  = filterX [1,5,10]+        | 4 < log10 ratio'  = filterX [1,5,10]         | 6 < ratio'        = filterX [1..10]         | 3 < ratio'        = filterX [1,1.2..10]         | otherwise         = steps 50 (dl', dh')---log10 :: (Floating a) => a -> a-log10 = logBase 10  $( makeLenses ''LinearAxisParams ) $( makeLenses ''LogAxisParams )
Graphics/Rendering/Chart/Axis/Indexed.hs view
@@ -7,14 +7,15 @@ -- Calculate and render indexed axes  {-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE TupleSections #-}  module Graphics.Rendering.Chart.Axis.Indexed(     PlotIndex(..),+    autoIndexAxis',     autoIndexAxis,     addIndexes, ) where -import Control.Arrow (first)  import Data.Default.Class  import Graphics.Rendering.Chart.Axis.Types@@ -31,18 +32,18 @@  -- | Augment a list of values with index numbers for plotting. addIndexes :: [a] -> [(PlotIndex,a)]-addIndexes as = map (first PlotIndex) (zip [0..] as)+addIndexes = zipWith (\n x -> (PlotIndex n, x)) [0..]  -- | Create an axis for values indexed by position. The --   list of strings are the labels to be used.-autoIndexAxis :: Integral i => [String] -> [i] -> AxisData i-autoIndexAxis labels vs = AxisData {+autoIndexAxis' :: Integral i => Bool -> [String] -> AxisFn i+autoIndexAxis' tks labels vs = AxisData {     _axis_visibility = def { _axis_show_ticks = False },     _axis_viewport = vport,     _axis_tropweiv = invport,-    _axis_ticks    = [],+    _axis_ticks    = if tks then map (, 5) $ take (length labels) [0..] else [],     _axis_labels   = [filter (\(i,_) -> i >= imin && i <= imax)-                            (zip [0..] labels)],+                             (zip [0..] labels)],     _axis_grid     = []     }   where@@ -51,3 +52,6 @@     invport = invLinMap round fromIntegral (imin, imax)     imin = minimum vs     imax = maximum vs++autoIndexAxis :: Integral i => [String] -> AxisFn i+autoIndexAxis = autoIndexAxis' False
Graphics/Rendering/Chart/Axis/Int.hs view
@@ -14,11 +14,58 @@ ) where  import Data.List(genericLength)+import Data.Int (Int8, Int16, Int32, Int64)+import Data.Word (Word8, Word16, Word32, Word64) import Graphics.Rendering.Chart.Geometry import Graphics.Rendering.Chart.Axis.Types import Graphics.Rendering.Chart.Axis.Floating  instance PlotValue Int where+    toValue    = fromIntegral+    fromValue  = round+    autoAxis   = autoScaledIntAxis defaultIntAxis++instance PlotValue Int8 where+    toValue    = fromIntegral+    fromValue  = round+    autoAxis   = autoScaledIntAxis defaultIntAxis++instance PlotValue Int16 where+    toValue    = fromIntegral+    fromValue  = round+    autoAxis   = autoScaledIntAxis defaultIntAxis++instance PlotValue Int32 where+    toValue    = fromIntegral+    fromValue  = round+    autoAxis   = autoScaledIntAxis defaultIntAxis++instance PlotValue Int64 where+    toValue    = fromIntegral+    fromValue  = round+    autoAxis   = autoScaledIntAxis defaultIntAxis++instance PlotValue Word where+    toValue    = fromIntegral+    fromValue  = round+    autoAxis   = autoScaledIntAxis defaultIntAxis++instance PlotValue Word8 where+    toValue    = fromIntegral+    fromValue  = round+    autoAxis   = autoScaledIntAxis defaultIntAxis++instance PlotValue Word16 where+    toValue    = fromIntegral+    fromValue  = round+    autoAxis   = autoScaledIntAxis defaultIntAxis++instance PlotValue Word32 where+    toValue    = fromIntegral+    fromValue  = round+    autoAxis   = autoScaledIntAxis defaultIntAxis++instance PlotValue Word64 where     toValue    = fromIntegral     fromValue  = round     autoAxis   = autoScaledIntAxis defaultIntAxis
Graphics/Rendering/Chart/Backend/Impl.hs view
@@ -10,7 +10,7 @@  module Graphics.Rendering.Chart.Backend.Impl where -import Control.Monad.Reader+import Control.Monad import Control.Monad.Operational  import Graphics.Rendering.Chart.Geometry@@ -22,20 +22,20 @@  -- | The abstract drawing operation generated when using the --   the chart drawing API.---   +-- --   See the documentation of the different function for the correct semantics --   of each instruction:---   +-- --   * 'strokePath', 'fillPath'---   +-- --   * 'drawText', 'textSize'---   +-- --   * 'getPointAlignFn', 'getCoordAlignFn', 'AlignmentFns'---   +-- --   * 'withTransform', 'withClipRegion'---   +-- --   * 'withLineStyle', 'withFillStyle', 'withFontStyle'---   +-- data ChartBackendInstr a where   StrokePath :: Path -> ChartBackendInstr ()   FillPath   :: Path -> ChartBackendInstr ()@@ -49,22 +49,22 @@   WithClipRegion :: Rect -> Program ChartBackendInstr a -> ChartBackendInstr a  -- | A 'BackendProgram' provides the capability to render a chart somewhere.---   +-- --   The coordinate system of the backend has its initial origin (0,0)---   in the top left corner of the drawing plane. The x-axis points ---   towards the top right corner and the y-axis points towards +--   in the top left corner of the drawing plane. The x-axis points+--   towards the top right corner and the y-axis points towards --   the bottom left corner. The unit used by coordinates, the font size, --   and lengths is the always the same, but depends on the backend. --   All angles are measured in radians.---   ---   The line, fill and font style are set to their default values +--+--   The line, fill and font style are set to their default values --   initially.---   ---   Information about the semantics of the instructions can be +--+--   Information about the semantics of the instructions can be --   found in the documentation of 'ChartBackendInstr'. type BackendProgram a = Program ChartBackendInstr a --- | Stroke the outline of the given path using the +-- | Stroke the outline of the given path using the --   current 'LineStyle'. This function does /not/ perform --   alignment operations on the path. See 'Path' for the exact semantic --   of paths.@@ -84,13 +84,13 @@ textSize :: String -> BackendProgram TextSize textSize text = singleton (GetTextSize text) --- | Draw a single-line textual label anchored by the baseline (vertical) +-- | Draw a single-line textual label anchored by the baseline (vertical) --   left (horizontal) point. Uses the current 'FontStyle' for drawing. drawText :: Point -> String -> BackendProgram () drawText p text = singleton (DrawText p text)  -- | Apply the given transformation in this local---   environment when drawing. The given transformation +--   environment when drawing. The given transformation --   is applied after the current transformation. This --   means both are combined. withTransform :: Matrix -> BackendProgram a -> BackendProgram a@@ -98,11 +98,11 @@  -- | Use the given font style in this local --   environment when drawing text.---   ---   An implementing backend is expected to guarentee+--+--   An implementing backend is expected to guarantee --   to support the following font families: @serif@, @sans-serif@ and @monospace@;---   ---   If the backend is not able to find or load a given font +--+--   If the backend is not able to find or load a given font --   it is required to fall back to a custom fail-safe font --   and use it instead. withFontStyle :: FontStyle -> BackendProgram a -> BackendProgram a@@ -120,7 +120,7 @@  -- | Use the given clipping rectangle when drawing --   in this local environment. The new clipping region---   is intersected with the given clip region. You cannot +--   is intersected with the given clip region. You cannot --   escape the clip! withClipRegion :: Rect -> BackendProgram a -> BackendProgram a withClipRegion c p = singleton (WithClipRegion c p)
Graphics/Rendering/Chart/Drawing.hs view
@@ -27,20 +27,20 @@     PointShape(..)   , PointStyle(..)   , drawPoint-  +   -- * Alignments and Paths   , alignPath   , alignFillPath   , alignStrokePath   , alignFillPoints   , alignStrokePoints-  +   , alignFillPoint   , alignStrokePoint-  +   , strokePointPath   , fillPointPath-  +   -- * Transformation and Style Helpers   , withRotation   , withTranslation@@ -48,17 +48,17 @@   , withScaleX, withScaleY   , withPointStyle   , withDefaultStyle-  +   -- * Text Drawing   , drawTextA   , drawTextR   , drawTextsR   , textDrawRect   , textDimension-  +   -- * Style Helpers   , defaultColorSeq-    +   , solidLine   , dashedLine @@ -70,12 +70,12 @@   , exes   , stars   , arrows-    +   , solidFillStyle-  +   -- * Backend and general Types   , module Graphics.Rendering.Chart.Backend-  +   -- * Accessors   , point_color   , point_border_color@@ -95,7 +95,6 @@ import Data.Colour import Data.Colour.Names import Data.List (unfoldr)-import Data.Monoid  import Graphics.Rendering.Chart.Backend import Graphics.Rendering.Chart.Geometry hiding (moveTo)@@ -128,8 +127,8 @@ -- | Changes the 'LineStyle' and 'FillStyle' to comply with --   the given 'PointStyle'. withPointStyle :: PointStyle -> BackendProgram a -> BackendProgram a-withPointStyle (PointStyle cl bcl bw _ _) m = -  withLineStyle (def { _line_color = bcl, _line_width = bw, _line_join = LineJoinMiter }) $ +withPointStyle (PointStyle cl bcl bw _ _) m =+  withLineStyle (def { _line_color = bcl, _line_width = bw, _line_join = LineJoinMiter }) $     withFillStyle (solidFillStyle cl) m  withDefaultStyle :: BackendProgram a -> BackendProgram a@@ -148,7 +147,7 @@                        close  -- | Align the path using the environment's alignment function for points.---   This is generally useful when stroking. +--   This is generally useful when stroking. --   See 'alignPath' and 'getPointAlignFn'. alignStrokePath :: Path -> BackendProgram Path alignStrokePath p = do@@ -156,7 +155,7 @@   return $ alignPath f p  -- | Align the path using the environment's alignment function for coordinates.---   This is generally useful when filling. +--   This is generally useful when filling. --   See 'alignPath' and 'getCoordAlignFn'. alignFillPath :: Path -> BackendProgram Path alignFillPath p = do@@ -182,14 +181,14 @@ -- | Align the point using the environment's alignment function for points. --   See 'getPointAlignFn'. alignStrokePoint :: Point -> BackendProgram Point-alignStrokePoint p = do +alignStrokePoint p = do     alignfn <- getPointAlignFn     return (alignfn p)  -- | Align the point using the environment's alignment function for coordinates. --   See 'getCoordAlignFn'. alignFillPoint :: Point -> BackendProgram Point-alignFillPoint p = do +alignFillPoint p = do     alignfn <- getCoordAlignFn     return (alignfn p) @@ -217,19 +216,19 @@ drawTextA :: HTextAnchor -> VTextAnchor -> Point -> String -> BackendProgram () drawTextA hta vta = drawTextR hta vta 0 -{- +{-    The following is useful for checking out the bounding-box    calculation. At present it looks okay for PNG/Cairo but    is a bit off for SVG/Diagrams; this may well be down to    differences in how fonts are rendered in the two backends  drawTextA hta vta p txt =-  drawTextR hta vta 0 p txt -  >> withLineStyle (solidLine 1 (opaque red)) +  drawTextR hta vta 0 p txt+  >> withLineStyle (solidLine 1 (opaque red))      (textDrawRect hta vta p txt        >>= \rect -> alignStrokePath (rectPath rect) >>= strokePath) -}-  + -- | Draw a textual label anchored by one of its corners --   or edges, with rotation. Rotation angle is given in degrees, --   rotation is performed around anchor point.@@ -251,7 +250,7 @@ drawTextsR hta vta angle p s = case num of       0 -> return ()       1 -> drawTextR hta vta angle p s-      _ -> +      _ ->         withTranslation p $           withRotation theta $ do             tss <- mapM textSize ss@@ -320,7 +319,7 @@ textDimension s = do   ts <- textSize s   return (textSizeWidth ts, textSizeHeight ts)-  + -- ----------------------------------------------------------------------- -- Point Types and Drawing -- -----------------------------------------------------------------------@@ -350,7 +349,7 @@  -- | Default style to use for points. instance Default PointStyle where-  def = PointStyle +  def = PointStyle     { _point_color        = opaque black     , _point_border_color = transparent     , _point_border_width = 0@@ -383,7 +382,7 @@     PointShapeArrowHead theta ->       withTranslation p $ withRotation (theta - pi/2) $           drawPoint (filledPolygon r 3 True cl) (Point 0 0)-    PointShapePlus -> +    PointShapePlus ->       strokePath $ moveTo' (x+r) y                 <> lineTo' (x-r) y                 <> moveTo' x (y-r)@@ -436,7 +435,7 @@ filledCircles :: Double             -- ^ Radius of circle.               -> AlphaColour Double -- ^ Fill colour.               -> PointStyle-filledCircles radius cl = +filledCircles radius cl =   PointStyle cl transparent 0 radius PointShapeCircle  -- | Style for stroked circle points.@@ -444,7 +443,7 @@               -> Double -- ^ Thickness of line.               -> AlphaColour Double -- Colour of line.               -> PointStyle-hollowCircles radius w cl = +hollowCircles radius w cl =   PointStyle transparent cl w radius PointShapeCircle  -- | Style for stroked polygon points.@@ -454,7 +453,7 @@               -> Bool   -- ^ Is right-side-up?               -> AlphaColour Double -- ^ Colour of line.               -> PointStyle-hollowPolygon radius w sides isrot cl = +hollowPolygon radius w sides isrot cl =   PointStyle transparent cl w radius (PointShapePolygon sides isrot)  -- | Style for filled polygon points.@@ -463,7 +462,7 @@               -> Bool   -- ^ Is right-side-up?               -> AlphaColour Double -- ^ Fill color.               -> PointStyle-filledPolygon radius sides isrot cl = +filledPolygon radius sides isrot cl =   PointStyle cl transparent 0 radius (PointShapePolygon sides isrot)  -- | Plus sign point style.@@ -471,7 +470,7 @@         -> Double -- ^ Thickness of line.         -> AlphaColour Double -- ^ Color of line.         -> PointStyle-plusses radius w cl = +plusses radius w cl =   PointStyle transparent cl w radius PointShapePlus  -- | Cross point style.
Graphics/Rendering/Chart/Easy.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE ScopedTypeVariables, TemplateHaskell, TypeSynonymInstances, FlexibleInstances #-}+{-# LANGUAGE ScopedTypeVariables, FlexibleInstances #-} ---------------------------------------------------------------------------- -- | -- Module      :  Graphics.Rendering.Chart.Easy@@ -6,7 +6,7 @@ -- License     :  BSD-style (see chart/COPYRIGHT) -- -- A high level API for generating a plot quickly.--- +-- -- Importing the Easy module brings into scope all core functions and types required -- for working with the chart library. This includes key external dependencies such as -- Control.Lens and Data.Colour. The module also provides several helper functions for@@ -17,10 +17,10 @@ -- -- > import Graphics.Rendering.Chart.Easy -- > import Graphics.Rendering.Chart.Backend.Cairo--- > +-- > -- > signal :: [Double] -> [(Double,Double)] -- > signal xs = [ (x,(sin (x*3.14159/45) + 1) / 2 * (sin (x*3.14159/5))) | x <- xs ]--- > +-- > -- > main = toFile def "example.png" $ do -- >     layout_title .= "Amplitude Modulation" -- >     plot (line "am" [signal [0,(0.5)..400]])@@ -46,7 +46,7 @@   ) where  import Control.Lens-import Control.Monad(when)+import Control.Monad(unless) import Data.Default.Class import Data.Colour hiding (over) -- overlaps with lens over function import Data.Colour.Names@@ -83,9 +83,9 @@     plot_points_style . point_color .= color     plot_points_style . point_shape .= shape     plot_points_style . point_radius .= 2-    +     -- Show borders for unfilled shapes-    when (not (isFilled shape)) $ do+    unless (isFilled shape) $ do         plot_points_style . point_border_color .= color         plot_points_style . point_border_width .= 1 @@ -93,9 +93,9 @@ isFilled PointShapeCircle = True isFilled PointShapePolygon{} = True isFilled _ = False-    + -- | Construct a bar chart with the given titles and data, using the--- next available colors    +-- next available colors bars :: (PlotValue x, BarsPlotValue y) => [String] -> [(x,[y])] -> EC l (PlotBars x y) bars titles vals = liftEC $ do     styles <- sequence [fmap mkStyle takeColor | _ <- titles]
Graphics/Rendering/Chart/Geometry.hs view
@@ -53,8 +53,6 @@  import qualified Prelude import Prelude hiding ((^))-import Data.Monoid (Monoid (..))-import Data.Semigroup (Semigroup(..))  -- The homomorphic version to avoid casts inside the code. (^) :: Num a => a -> Integer -> a
Graphics/Rendering/Chart/Layout.hs view
@@ -11,11 +11,11 @@ -- (see 'Control.Lens') for each field of the following data types: -- --     * 'Layout'---     +-- --     * 'LayoutLR'--- +-- --     * 'StackedLayouts'--- +-- --     * 'LayoutAxis' -- {-# LANGUAGE CPP #-}@@ -33,12 +33,12 @@   , StackedLayout(..)   -- , LegendItem  haddock complains about this being missing, but from what?   , MAxisFn-  +     -- * Rendering   , layoutToRenderable-  , layoutToGrid  +  , layoutToGrid   , layoutLRToRenderable-  , layoutLRToGrid  +  , layoutLRToGrid   , renderStackedLayouts      -- * LayoutAxis lenses@@ -48,7 +48,7 @@   , laxis_generate   , laxis_override   , laxis_reverse-    +     -- * Layout lenses   , layout_background   , layout_plot_background@@ -69,7 +69,7 @@   , layout_axes_title_styles   , layout_all_font_styles   , layout_foreground-      +     -- * LayoutLR lenses   , layoutlr_background   , layoutlr_plot_background@@ -114,18 +114,17 @@ import Data.Colour import Data.Colour.Names (white) import Data.Default.Class-import Data.Maybe (fromMaybe)  -- | A @MAxisFn@ is a function that generates an (optional) axis --   given the points plotted against that axis. type MAxisFn t = [t] -> Maybe (AxisData t)  -- | Type of axis that is used in 'Layout' and 'LayoutLR'.---   +-- --   To generate the actual axis type ('AxisData' and 'AxisT') --   the '_laxis_generate' function is called and custom settings --   are applied with '_laxis_override'. Note that the 'AxisVisibility'---   values in 'Layout' and 'LayoutLR' override visibility related +--   values in 'Layout' and 'LayoutLR' override visibility related --   settings of the axis. data LayoutAxis x = LayoutAxis   { _laxis_title_style :: FontStyle@@ -138,29 +137,29 @@   , _laxis_generate    :: AxisFn x     -- ^ Function that generates the axis data, based upon the     --   points plotted. The default value is 'autoAxis'.-  +   , _laxis_override    :: AxisData x -> AxisData x     -- ^ Function that can be used to override the generated axis data.     --   The default value is 'id'.-  +   , _laxis_reverse     :: Bool     -- ^ True if left to right (bottom to top) is to show descending values.-  +   }  -- | Information on what is at a specifc location of a 'Layout' or 'LayoutLR'. --   This is delivered by the 'PickFn' of a 'Renderable'.-data LayoutPick x y1 y2 = LayoutPick_Legend String -- ^ A legend entry.-                          | LayoutPick_Title String  -- ^ The title.-                          | LayoutPick_XTopAxisTitle String      -- ^ The title of the top x axis.-                          | LayoutPick_XBottomAxisTitle String   -- ^ The title of the bottom x axis.-                          | LayoutPick_YLeftAxisTitle String  -- ^ The title of the left y axis.-                          | LayoutPick_YRightAxisTitle String -- ^ The title of the right y axis.-                          | LayoutPick_PlotArea x y1 y2 -- ^ The plot area at the given plot coordinates.-                          | LayoutPick_XTopAxis x       -- ^ The top x axis at the given plot coordinate.-                          | LayoutPick_XBottomAxis x    -- ^ The bottom x axis at the given plot coordinate.-                          | LayoutPick_YLeftAxis y1  -- ^ The left y axis at the given plot coordinate.-                          | LayoutPick_YRightAxis y2 -- ^ The right y axis at the given plot coordinate.+data LayoutPick x y1 y2 = LayoutPick_Legend String           -- ^ A legend entry.+                        | LayoutPick_Title String            -- ^ The title.+                        | LayoutPick_XTopAxisTitle String    -- ^ The title of the top x axis.+                        | LayoutPick_XBottomAxisTitle String -- ^ The title of the bottom x axis.+                        | LayoutPick_YLeftAxisTitle String   -- ^ The title of the left y axis.+                        | LayoutPick_YRightAxisTitle String  -- ^ The title of the right y axis.+                        | LayoutPick_PlotArea x y1 y2        -- ^ The plot area at the given plot coordinates.+                        | LayoutPick_XTopAxis x              -- ^ The top x axis at the given plot coordinate.+                        | LayoutPick_XBottomAxis x           -- ^ The bottom x axis at the given plot coordinate.+                        | LayoutPick_YLeftAxis y1            -- ^ The left y axis at the given plot coordinate.+                        | LayoutPick_YRightAxis y2           -- ^ The right y axis at the given plot coordinate.                           deriving (Show)  type LegendItem = (String,Rect -> BackendProgram ())@@ -169,11 +168,11 @@ --   axis. The title is at the top and the legend at the bottom. It's --   parametrized by the types of values to be plotted on the x --   and y axes.-data Layout x y = Layout +data Layout x y = Layout   { _layout_background      :: FillStyle     -- ^ How to fill the background of everything.   , _layout_plot_background :: Maybe FillStyle-    -- ^ How to fill the background of the plot, +    -- ^ How to fill the background of the plot,     --   if different from the overall background.    , _layout_title           :: String@@ -219,7 +218,7 @@ layoutToGrid l = grid   where     lp :: Grid a -> a -> Grid a-    lp = case fromMaybe LegendBelow $ _legend_position <$> _layout_legend l of+    lp = case maybe LegendBelow _legend_position $ _layout_legend l of               LegendAbove -> flip wideAbove               LegendBelow -> aboveWide               LegendRight -> besideTall@@ -245,7 +244,7 @@     g      = besideN [ tval $ mkLegend (_layout_legend l) (_layout_margin l) legItems                      , weights (1,1) $ tval emptyRenderable ] --- | Render the plot area of a 'Layout'. This consists of the +-- | Render the plot area of a 'Layout'. This consists of the --   actual plot area with all plots, the axis and their titles. layoutPlotAreaToGrid :: forall x y. (Ord x, Ord y) =>                         Layout x y -> Grid (Renderable (LayoutPick x y y))@@ -303,7 +302,7 @@             mapx (AxisT _ _ rev ad) = _axis_tropweiv ad (optPairReverse rev xr)             mapy (AxisT _ _ rev ad) = _axis_tropweiv ad (optPairReverse rev yr) --- | Empty 'Layout' without title and plots. The background is white and +-- | Empty 'Layout' without title and plots. The background is white and --   the grid is drawn beneath all plots. There will be a legend. The top --   and right axis will not be visible. instance (PlotValue x, PlotValue y) => Default (Layout x y) where@@ -314,7 +313,7 @@     , _layout_title           = ""     , _layout_title_style     = def { _font_size   = 15                                     , _font_weight = FontWeightBold }-    +     , _layout_x_axis                 = def     , _layout_top_axis_visibility    = def { _axis_show_line   = False                                            , _axis_show_ticks  = False@@ -333,16 +332,16 @@     }  -----------------------------------------------------------------------  + -- | A LayoutLR value is a single plot area, with an x axis and --   independent left and right y axes, with a title at the top; --   legend at the bottom. It's parametrized by the types of values --   to be plotted on the x and two y axes.-data LayoutLR x y1 y2 = LayoutLR +data LayoutLR x y1 y2 = LayoutLR   { _layoutlr_background      :: FillStyle     -- ^ How to fill the background of everything.   , _layoutlr_plot_background :: Maybe FillStyle-    -- ^ How to fill the background of the plot, +    -- ^ How to fill the background of the plot,     --   if different from the overall background.    , _layoutlr_title           :: String@@ -365,7 +364,7 @@     -- ^ Rules to generate the right y axis.   , _layoutlr_right_axis_visibility :: AxisVisibility     -- ^ Visibility options for the right axis.-  +   , _layoutlr_plots      :: [Either (Plot x y1) (Plot x y2)]     -- ^ The data sets to plot in the chart.     --   They are plotted over each other.@@ -385,12 +384,12 @@   toRenderable = setPickFn nullPickFn . layoutLRToRenderable  -- | Render the given 'LayoutLR'.-layoutLRToRenderable :: forall x yl yr . (Ord x, Ord yl, Ord yr) +layoutLRToRenderable :: forall x yl yr . (Ord x, Ord yl, Ord yr)                      => LayoutLR x yl yr -> Renderable (LayoutPick x yl yr)-layoutLRToRenderable l = fillBackground (_layoutlr_background l) +layoutLRToRenderable l = fillBackground (_layoutlr_background l)                        $ gridToRenderable (layoutLRToGrid l) -layoutLRToGrid :: forall x yl yr . (Ord x, Ord yl, Ord yr) +layoutLRToGrid :: forall x yl yr . (Ord x, Ord yl, Ord yr)                      => LayoutLR x yl yr -> Grid (Renderable (LayoutPick x yl yr)) layoutLRToGrid l = grid   where@@ -425,8 +424,8 @@                      , tval $ mkLegend (_layoutlr_legend l) (_layoutlr_margin l) rights ]     -- lm     = _layoutlr_margin l -layoutLRPlotAreaToGrid :: forall x yl yr. (Ord x, Ord yl, Ord yr) -                       => LayoutLR x yl yr +layoutLRPlotAreaToGrid :: forall x yl yr. (Ord x, Ord yl, Ord yr)+                       => LayoutLR x yl yr                        -> Grid (Renderable (LayoutPick x yl yr)) layoutLRPlotAreaToGrid l = buildGrid LayoutGridElements{   lge_plots = mfill (_layoutlr_plot_background l) $ plotsToRenderable l,@@ -441,7 +440,7 @@           ++ [ x | (Right p) <- _layoutlr_plots l, x <- fst $ _plot_all_points p]     yvalsL = [ y | (Left p)  <- _layoutlr_plots l, y <- snd $ _plot_all_points p]     yvalsR = [ y | (Right p) <- _layoutlr_plots l, y <- snd $ _plot_all_points p]-    +     bAxis = mkAxis E_Bottom (overrideAxisVisibility l _layoutlr_x_axis _layoutlr_bottom_axis_visibility) xvals     tAxis = mkAxis E_Top    (overrideAxisVisibility l _layoutlr_x_axis _layoutlr_top_axis_visibility   ) xvals     lAxis = mkAxis E_Left   (overrideAxisVisibility l _layoutlr_left_axis  _layoutlr_left_axis_visibility ) yvalsL@@ -494,7 +493,7 @@  -- | A container for a set of vertically 'StackedLayout's. --   The x axis of the different layouts will be aligned.-data StackedLayouts x = StackedLayouts +data StackedLayouts x = StackedLayouts   { _slayouts_layouts :: [StackedLayout x]     -- ^ The stacked layouts from top (first element) to bottom (last element).   , _slayouts_compress_legend :: Bool@@ -522,7 +521,7 @@   where     g = fullOverlayUnder (fillBackground bg emptyRenderable)       $ foldr (above.mkGrid) nullt (zip sls [0,1..])-    +     mkGrid :: (StackedLayout x, Int) -> Grid (Renderable ())     mkGrid (sl, i)         = titleR@@ -537,21 +536,21 @@         legendR = case sl of                     StackedLayout l -> noPickFn $ renderLegend l $ fst legenditems                     StackedLayoutLR l -> noPickFn $ renderLegendLR l legenditems-        +         legenditems = case (_slayouts_compress_legend slp,isBottomPlot) of             (False,_) -> case sl of                            StackedLayout l -> (getLegendItems l, [])                            StackedLayoutLR l -> getLegendItemsLR l             (True,True) -> allLegendItems             (True,False) -> ([],[])-        +         mkPlotArea :: LayoutAxis x -> Grid (Renderable ())         mkPlotArea axis = case sl of-          StackedLayout l -> fmap noPickFn -                           $ layoutPlotAreaToGrid +          StackedLayout l -> fmap noPickFn+                           $ layoutPlotAreaToGrid                            $ l { _layout_x_axis = axis }-          StackedLayoutLR l -> fmap noPickFn -                             $ layoutLRPlotAreaToGrid +          StackedLayoutLR l -> fmap noPickFn+                             $ layoutLRPlotAreaToGrid                              $ l { _layoutlr_x_axis = axis }          showLegend = not (null (fst legenditems)) || not (null (snd legenditems))@@ -561,37 +560,37 @@         lm = case sl of           StackedLayout l -> _layout_margin l           StackedLayoutLR l -> _layoutlr_margin l-        +         xAxis :: LayoutAxis x         xAxis = case sl of           StackedLayout l -> _layout_x_axis l           StackedLayoutLR l -> _layoutlr_x_axis l-        +         usedAxis :: LayoutAxis x-        usedAxis = xAxis +        usedAxis = xAxis           { _laxis_generate = const (_laxis_generate xAxis all_xvals) }-        +     bg = case sl1 of            StackedLayout l -> _layout_background l            StackedLayoutLR l -> _layoutlr_background l-    +     getXVals :: StackedLayout x -> [x]     getXVals (StackedLayout l) = getLayoutXVals l     getXVals (StackedLayoutLR l) = getLayoutLRXVals l-    +     all_xvals = concatMap getXVals sls      allLegendItems = (concatMap (fst.legendItems) sls, concatMap (snd.legendItems) sls)-    +     legendItems :: StackedLayout x -> ([LegendItem], [LegendItem])     legendItems (StackedLayout l)   = (getLegendItems l, [])     legendItems (StackedLayoutLR l) = getLegendItemsLR l-    +     noPickFn :: Renderable a -> Renderable ()     noPickFn = mapPickFn (const ())  -----------------------------------------------------------------------    + addMarginsToGrid :: (Double,Double,Double,Double) -> Grid (Renderable a)                  -> Grid (Renderable a) addMarginsToGrid (t,b,l,r) g = aboveN [@@ -623,7 +622,7 @@  data LayoutGridElements x yl yr = LayoutGridElements {   lge_plots :: Renderable (LayoutPick x yl yr),-  +   lge_taxis :: (Maybe (AxisT x),String,FontStyle),   lge_baxis :: (Maybe (AxisT x),String,FontStyle),   lge_laxis :: (Maybe (AxisT yl),String,FontStyle),@@ -660,7 +659,7 @@     (btitle,_) = mktitle HTA_Centre VTA_Top      0 blbl bstyle LayoutPick_XBottomAxisTitle     (ltitle,lam) = mktitle HTA_Right  VTA_Centre 270 llbl lstyle LayoutPick_YLeftAxisTitle     (rtitle,ram) = mktitle HTA_Left   VTA_Centre 270 rlbl rstyle LayoutPick_YRightAxisTitle-    +     baxis = tval $ maybe emptyRenderable                          (mapPickFn LayoutPick_XBottomAxis . axisToRenderable) bdata     taxis = tval $ maybe emptyRenderable@@ -675,10 +674,10 @@     tr = tval $ axesSpacer snd tdata fst rdata     br = tval $ axesSpacer snd bdata snd rdata -    mktitle :: HTextAnchor -> VTextAnchor +    mktitle :: HTextAnchor -> VTextAnchor             -> Double             -> String -> FontStyle-            -> (String -> LayoutPick x yl yr) +            -> (String -> LayoutPick x yl yr)             -> ( Grid (Renderable (LayoutPick x yl yr))                , Grid (Renderable (LayoutPick x yl yr)) )     mktitle ha va rot lbl style pf = if lbl == "" then (er,er) else (labelG,gapG)@@ -713,7 +712,7 @@   in _plot_render p pmfn renderSinglePlot _ _ _ _ = return () -axesSpacer :: (Ord x, Ord y) +axesSpacer :: (Ord x, Ord y)            => ((Double, Double) -> Double) -> Maybe (AxisT x)            -> ((Double, Double) -> Double) -> Maybe (AxisT y)            -> Renderable a@@ -722,12 +721,12 @@     oh2 <- maybeM (0,0) axisOverhang a2     return (spacer (f1 oh1, f2 oh2)) --- | Construct a axis for the given edge using the attributes +-- | Construct a axis for the given edge using the attributes --   from a 'LayoutAxis' the given values. mkAxis :: RectEdge -> LayoutAxis z -> [z] -> Maybe (AxisT z)-mkAxis edge laxis vals = case axisVisible of-    False -> Nothing-    True  -> Just $ AxisT edge style rev adata+mkAxis edge laxis vals = if axisVisible+                           then Just $ AxisT edge style rev adata+                           else Nothing   where     style = _laxis_style laxis     rev   = _laxis_reverse laxis@@ -736,13 +735,13 @@     axisVisible = _axis_show_labels vis || _axis_show_line vis || _axis_show_ticks vis  -- | Override the visibility of a selected axis with the selected 'AxisVisibility'.-overrideAxisVisibility :: layout -                       -> (layout -> LayoutAxis z) -                       -> (layout -> AxisVisibility) -                       -> LayoutAxis z -overrideAxisVisibility ly selAxis selVis = +overrideAxisVisibility :: layout+                       -> (layout -> LayoutAxis z)+                       -> (layout -> AxisVisibility)+                       -> LayoutAxis z+overrideAxisVisibility ly selAxis selVis =   let vis = selVis ly-  in (selAxis ly) { _laxis_override = (\ad -> ad { _axis_visibility = vis }) +  in (selAxis ly) { _laxis_override = (\ad -> ad { _axis_visibility = vis })                                     . _laxis_override (selAxis ly)                   } @@ -750,7 +749,7 @@ mfill Nothing   = id mfill (Just fs) = fillBackground fs --- | Empty 'LayoutLR' without title and plots. The background is white and +-- | Empty 'LayoutLR' without title and plots. The background is white and --   the grid is drawn beneath all plots. There will be a legend. The top --   axis will not be visible. instance (PlotValue x, PlotValue y1, PlotValue y2) => Default (LayoutLR x y1 y2) where@@ -772,7 +771,7 @@     , _layoutlr_left_axis_visibility  = def     , _layoutlr_right_axis          = def     , _layoutlr_right_axis_visibility = def-    +     , _layoutlr_plots      = []      , _layoutlr_legend          = Just def@@ -800,19 +799,19 @@  -- | Setter to update all axis styles on a `Layout` layout_axes_styles :: Setter' (Layout x y) AxisStyle-layout_axes_styles = sets $ \af -> +layout_axes_styles = sets $ \af ->     (layout_x_axis . laxis_style %~ af) .-    (layout_y_axis . laxis_style %~ af) +    (layout_y_axis . laxis_style %~ af)  -- | Setter to update all the axes title styles on a `Layout` layout_axes_title_styles :: Setter' (Layout x y) FontStyle-layout_axes_title_styles = sets $ \af -> +layout_axes_title_styles = sets $ \af ->     (layout_x_axis . laxis_title_style %~ af) .     (layout_y_axis . laxis_title_style %~ af)  -- | Setter to update all the font styles on a `Layout` layout_all_font_styles :: Setter' (Layout x y) FontStyle-layout_all_font_styles = sets $ \af -> +layout_all_font_styles = sets $ \af ->     (layout_axes_title_styles %~ af) .     (layout_x_axis . laxis_style . axis_label_style %~ af) .     (layout_y_axis . laxis_style . axis_label_style %~ af) .@@ -823,25 +822,25 @@ layout_foreground ::  Setter' (Layout x y) (AlphaColour Double) layout_foreground = sets $ \af ->     (layout_all_font_styles . font_color %~ af) .-    (layout_axes_styles . axis_line_style . line_color %~ af) +    (layout_axes_styles . axis_line_style . line_color %~ af)  -- | Setter to update all axis styles on a `LayoutLR` layoutlr_axes_styles :: Setter' (LayoutLR x y1 y2) AxisStyle-layoutlr_axes_styles = sets $ \af -> +layoutlr_axes_styles = sets $ \af ->     (layoutlr_x_axis . laxis_style %~ af) .     (layoutlr_left_axis . laxis_style %~ af) .     (layoutlr_right_axis . laxis_style %~ af)  -- | Setter to update all the axes title styles on a `LayoutLR` layoutlr_axes_title_styles :: Setter' (LayoutLR x y1 y2) FontStyle-layoutlr_axes_title_styles = sets $ \af -> +layoutlr_axes_title_styles = sets $ \af ->     (layoutlr_x_axis . laxis_title_style %~ af) .     (layoutlr_left_axis . laxis_title_style %~ af) .     (layoutlr_right_axis . laxis_title_style %~ af)  -- | Setter to update all the font styles on a `LayoutLR` layoutlr_all_font_styles :: Setter' (LayoutLR x y1 y2) FontStyle-layoutlr_all_font_styles = sets $ \af -> +layoutlr_all_font_styles = sets $ \af ->     (layoutlr_axes_title_styles %~ af) .     (layoutlr_x_axis . laxis_style . axis_label_style %~ af) .     (layoutlr_left_axis . laxis_style . axis_label_style %~ af) .@@ -853,4 +852,4 @@ layoutlr_foreground ::  Setter' (LayoutLR x y1 y2) (AlphaColour Double) layoutlr_foreground = sets $ \af ->     (layoutlr_all_font_styles . font_color %~ af) .-    (layoutlr_axes_styles . axis_line_style . line_color %~ af) +    (layoutlr_axes_styles . axis_line_style . line_color %~ af)
Graphics/Rendering/Chart/Plot/Annotation.hs view
@@ -16,15 +16,19 @@     plot_annotation_angle,     plot_annotation_style,     plot_annotation_background,+    plot_annotation_offset,     plot_annotation_values ) where  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.Plot.Types-import Data.Default.Class+import Graphics.Rendering.Chart.Drawing+import Graphics.Rendering.Chart.Geometry+import Graphics.Rendering.Chart.Plot.Types  -- | Value for describing a series of text annotations --   to be placed at arbitrary points on the graph. Annotations@@ -40,6 +44,7 @@       -- ^ Rectangle which style determines the background of the annotation       -- text and which '_rect_minsize' determines the additional width and       -- height of the background area+      _plot_annotation_offset  :: Vector,       _plot_annotation_values  :: [(x,y,String)] } @@ -63,6 +68,7 @@           values = _plot_annotation_values p           angle =  _plot_annotation_angle p           style =  _plot_annotation_style p+          offset = _plot_annotation_offset p           rectangle = _plot_annotation_background p           (x1,y1) = _rect_minsize rectangle           drawRect (x,y,s) = do@@ -77,18 +83,19 @@                   yvp VTA_Centre = y3 - (y1 + y2) / 2                   yvp VTA_Bottom = y3 - y2 - y1 / 2                   yvp VTA_BaseLine = y3 - y1 / 2 - textSizeAscent ts-              drawRectangle (Point (xvp hta) (yvp vta)) rectangle{ _rect_minsize = (x1+x2,y1+y2) }+              drawRectangle (Point (xvp hta) (yvp vta) `pvadd` offset) rectangle{ _rect_minsize = (x1+x2,y1+y2) }           drawOne (x,y,s) = drawTextsR hta vta angle (point x y) s-          point x y = pMap (LValue x, LValue y)+          point x y = pMap (LValue x, LValue y) `pvadd` offset  instance Default (PlotAnnotation x y) where-  def = PlotAnnotation +  def = PlotAnnotation     { _plot_annotation_hanchor = HTA_Centre     , _plot_annotation_vanchor = VTA_Centre     , _plot_annotation_angle   = 0     , _plot_annotation_style   = def     , _plot_annotation_background = def     , _plot_annotation_values  = []+    , _plot_annotation_offset  = Vector 0 0     }  $( makeLenses ''PlotAnnotation )
Graphics/Rendering/Chart/Plot/Bars.hs view
@@ -7,6 +7,7 @@ -- Bar Charts -- {-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TupleSections #-}  module Graphics.Rendering.Chart.Plot.Bars(     PlotBars(..),@@ -14,41 +15,70 @@     PlotBarsSpacing(..),     PlotBarsAlignment(..),     BarsPlotValue(..),+    BarHorizAnchor(..),+    BarVertAnchor(..),      plotBars,+    plotHBars,+     plot_bars_style,     plot_bars_item_styles,     plot_bars_titles,     plot_bars_spacing,     plot_bars_alignment,-    plot_bars_reference,     plot_bars_singleton_width,+    plot_bars_label_bar_hanchor,+    plot_bars_label_bar_vanchor,+    plot_bars_label_text_hanchor,+    plot_bars_label_text_vanchor,+    plot_bars_label_angle,+    plot_bars_label_style,+    plot_bars_label_offset,+     plot_bars_values, +    plot_bars_settings,+    plot_bars_values_with_labels,++    addLabels ) where +import Control.Arrow import Control.Lens import Control.Monad-import Data.List(nub,sort)-import Graphics.Rendering.Chart.Geometry hiding (x0, y0)-import Graphics.Rendering.Chart.Drawing-import Graphics.Rendering.Chart.Plot.Types-import Graphics.Rendering.Chart.Axis import Data.Colour (opaque) import Data.Colour.Names (black) import Data.Default.Class-+import Data.Tuple(swap)+import Data.List(nub,sort)+import Graphics.Rendering.Chart.Axis+import Graphics.Rendering.Chart.Drawing+import Graphics.Rendering.Chart.Geometry hiding (x0, y0)+import Graphics.Rendering.Chart.Plot.Types+import Graphics.Rendering.Chart.Utils class PlotValue a => BarsPlotValue a where-    barsReference :: a+    barsIsNull    :: a -> Bool+    -- | The starting level for the chart, a function of some statistic+    --   (normally the lowest value or just const 0).+    barsReference :: [a] -> a     barsAdd       :: a -> a -> a  instance BarsPlotValue Double where-    barsReference = 0+    barsIsNull a  = a == 0.0+    barsReference = const 0     barsAdd       = (+)+ instance BarsPlotValue Int where-    barsReference = 0+    barsIsNull a  = a == 0+    barsReference = const 0     barsAdd       = (+) +instance BarsPlotValue LogValue where+    barsIsNull (LogValue a) = a == 0.0+    barsReference as        =+      10.0 ^^ (floor (log10 $ minimum $ filter (/= 0.0) as) :: Integer)+    barsAdd                 = (+)+ data PlotBarsStyle     = BarsStacked   -- ^ Bars for a fixed x are stacked vertically                     --   on top of each other.@@ -70,148 +100,312 @@                        | BarsRight     -- ^ The right edge of bars is at deviceX      deriving (Show) +data BarHorizAnchor+    = BHA_Left+    | BHA_Centre+    | BHA_Right+     deriving (Show)++data BarVertAnchor+    = BVA_Bottom+    | BVA_Centre+    | BVA_Top+     deriving (Show)+ -- | Value describing how to plot a set of bars. --   Note that the input data is typed [(x,[y])], ie for each x value --   we plot several y values. Typically the size of each [y] list would --   be the same.-data PlotBars x y = PlotBars {+data BarsSettings = BarsSettings {    -- | This value specifies whether each value from [y] should be    --   shown beside or above the previous value.-   _plot_bars_style           :: PlotBarsStyle,+   _bars_settings_style           :: PlotBarsStyle,     -- | The style in which to draw each element of [y]. A fill style    --   is required, and if a linestyle is given, each bar will be    --   outlined.-   _plot_bars_item_styles     :: [ (FillStyle,Maybe LineStyle) ],--   -- | The title of each element of [y]. These will be shown in the legend.-   _plot_bars_titles          :: [String],+   _bars_settings_item_styles     :: [ (FillStyle,Maybe LineStyle) ],     -- | This value controls how the widths of the bars are    --   calculated. Either the widths of the bars, or the gaps between    --   them can be fixed.-   _plot_bars_spacing         :: PlotBarsSpacing,+   _bars_settings_spacing         :: PlotBarsSpacing,     -- | This value controls how bars for a fixed x are aligned with    --   respect to the device coordinate corresponding to x.-   _plot_bars_alignment       :: PlotBarsAlignment,+   _bars_settings_alignment       :: PlotBarsAlignment, -   -- | The starting level for the chart (normally 0).-   _plot_bars_reference       :: y,+   _bars_settings_singleton_width :: Double, -   _plot_bars_singleton_width :: Double,+   -- | The point on the bar to horizontally anchor the label to+   _bars_settings_label_bar_hanchor :: BarHorizAnchor, -   -- | The actual points to be plotted.-   _plot_bars_values          :: [ (x,[y]) ]-}+   -- | The point on the bar to vertically anchor the label to+   _bars_settings_label_bar_vanchor  :: BarVertAnchor, -instance BarsPlotValue y => Default (PlotBars x y) where-  def = PlotBars-    { _plot_bars_style           = BarsClustered-    , _plot_bars_item_styles     = cycle istyles-    , _plot_bars_titles          = []-    , _plot_bars_spacing         = BarsFixGap 10 2-    , _plot_bars_alignment       = BarsCentered-    , _plot_bars_values          = []-    , _plot_bars_singleton_width = 20-    , _plot_bars_reference       = barsReference+    -- | The anchor point on the label.+   _bars_settings_label_text_hanchor :: HTextAnchor,++    -- | The anchor point on the label.+   _bars_settings_label_text_vanchor :: VTextAnchor,++   -- | Angle, in degrees, to rotate the label about the anchor point.+   _bars_settings_label_angle   :: Double,++   -- | The style to use for the label.+   _bars_settings_label_style   :: FontStyle,++   -- | The offset from the anchor point to display the label at.+   _bars_settings_label_offset  :: Vector+}+instance Default BarsSettings where+  def = BarsSettings+    { _bars_settings_style              = BarsClustered+    , _bars_settings_item_styles        = cycle istyles+    , _bars_settings_spacing            = BarsFixGap 10 2+    , _bars_settings_alignment          = BarsCentered+    , _bars_settings_singleton_width    = 20+    , _bars_settings_label_bar_hanchor  = BHA_Centre+    , _bars_settings_label_bar_vanchor  = BVA_Top+    , _bars_settings_label_text_hanchor = HTA_Centre+    , _bars_settings_label_text_vanchor = VTA_Bottom+    , _bars_settings_label_angle        = 0+    , _bars_settings_label_style        = def+    , _bars_settings_label_offset       = Vector 0 0     }     where       istyles   = map mkstyle defaultColorSeq       mkstyle c = (solidFillStyle c, Just (solidLine 1.0 $ opaque black))+data PlotBars x y = PlotBars {+   _plot_bars_settings :: BarsSettings,+   -- | The title of each element of [y]. These will be shown in the legend.+   _plot_bars_titles :: [String],+   -- | The actual points to be plotted, and their labels+   _plot_bars_values_with_labels :: [(x, [(y, String)])]+}+instance Default (PlotBars x y) where+  def = PlotBars+    { _plot_bars_settings = def+    , _plot_bars_titles = []+    , _plot_bars_values_with_labels = []+    }  plotBars :: (BarsPlotValue y) => PlotBars x y -> Plot x y plotBars p = Plot {-        _plot_render     = renderPlotBars p,+        _plot_render     = \pmap -> renderBars s vals yref0+                                      (barRect pmap) (mapX pmap),         _plot_legend     = zip (_plot_bars_titles p)                                (map renderPlotLegendBars-                                    (_plot_bars_item_styles p)),-        _plot_all_points = allBarPoints p+                                    (_bars_settings_item_styles s)),+        _plot_all_points = allBarPoints s vals     }+  where+    s = _plot_bars_settings p+    vals = _plot_bars_values_with_labels p+    yref0 = refVal s vals -renderPlotBars :: (BarsPlotValue y) => PlotBars x y -> PointMapFn x y -> BackendProgram ()-renderPlotBars p pmap = case _plot_bars_style p of+    barRect pmap xos width x y0 y1 = Rect (Point (x'+xos) y0') (Point (x'+xos+width) y') where+      Point x' y' = mapXY pmap (x,y1)+      Point _ y0' = mapXY pmap (x,y0)++    mapX pmap x = p_x (mapXY pmap (x, yref0))++plotHBars :: (BarsPlotValue x) => PlotBars y x -> Plot x y+plotHBars p = Plot {+        _plot_render     = \pmap -> renderBars s vals xref0+                                      (barRect pmap) (mapY pmap),+        _plot_legend     = zip (_plot_bars_titles p)+                               (map renderPlotLegendBars+                                    (_bars_settings_item_styles s)),+        _plot_all_points = swap $ allBarPoints s vals+    }+  where+    s = _plot_bars_settings p+    vals = _plot_bars_values_with_labels p+    xref0 = refVal s vals++    barRect pmap yos height y x0 x1 = Rect (Point x0' (y'+yos)) (Point x' (y'+yos+height)) where+      Point x' y' = mapXY pmap (x1,y)+      Point x0' _ = mapXY pmap (x0,y)++    mapY pmap y = p_y (mapXY pmap (xref0, y))++renderBars :: (BarsPlotValue v) =>+              BarsSettings+           -> [(k, [(v, String)])]+           -> v+           -> (Double -> Double -> k -> v -> v -> Rect)+           -> (k -> Double)+           -> BackendProgram ()+renderBars p vals vref0 r mapk = case _bars_settings_style p of       BarsClustered -> forM_ vals clusteredBars       BarsStacked   -> forM_ vals stackedBars   where-    clusteredBars (x,ys) = do-       forM_ (zip3 [0,1..] ys styles) $ \(i, y, (fstyle,_)) -> -           withFillStyle fstyle $ -             alignFillPath (barPath (offset i) x yref0 y)+    clusteredBars (k,vs) = do+       let offset i = case _bars_settings_alignment p of+             BarsLeft     -> fromIntegral i * bsize+             BarsRight    -> fromIntegral (i-nvs) * bsize+             BarsCentered -> fromIntegral (2*i-nvs) * bsize/2+       forM_ (zip3 [0,1..] vs styles) $ \(i, (v, _), (fstyle,_)) ->+           unless (barsIsNull v) $+           withFillStyle fstyle $+             alignFillPath (barPath (offset i) k vref0 v)              >>= fillPath-       forM_ (zip3 [0,1..] ys styles) $ \(i, y, (_,mlstyle)) -> -           whenJust mlstyle $ \lstyle -> -             withLineStyle lstyle $ -               alignStrokePath (barPath (offset i) x yref0 y)+       forM_ (zip3 [0,1..] vs styles) $ \(i, (v, _), (_,mlstyle)) ->+           unless (barsIsNull v) $+           whenJust mlstyle $ \lstyle ->+             withLineStyle lstyle $+               alignStrokePath (barPath (offset i) k vref0 v)                >>= strokePath--    offset = case _plot_bars_alignment p of-      BarsLeft     -> \i -> fromIntegral i * width-      BarsRight    -> \i -> fromIntegral (i-nys) * width-      BarsCentered -> \i -> fromIntegral (2*i-nys) * width/2+       withFontStyle (_bars_settings_label_style p) $+           forM_ (zip [0,1..] vs) $ \(i, (v, txt)) ->+             unless (null txt) $ do+               let ha = _bars_settings_label_bar_hanchor p+               let va = _bars_settings_label_bar_vanchor p+               let pt = rectCorner ha va (r (offset i) bsize k vref0 v)+               drawTextR+                  (_bars_settings_label_text_hanchor p)+                  (_bars_settings_label_text_vanchor p)+                  (_bars_settings_label_angle p)+                  (pvadd pt $ _bars_settings_label_offset p)+                  txt -    stackedBars (x,ys) = do-       let y2s = zip (yref0:stack ys) (stack ys)-       let ofs = case _plot_bars_alignment p of+    stackedBars (k,vs) = do+       let (vs', lbls) = unzip vs+       let vs'' = map (\v -> if barsIsNull v then vref0 else v) (stack vs')+       let v2s = zip (vref0:vs'') vs''+       let ofs = case _bars_settings_alignment p of              BarsLeft     -> 0-             BarsRight    -> -width-             BarsCentered -> -(width/2)-       forM_ (zip y2s styles) $ \((y0,y1), (fstyle,_)) -> -           withFillStyle fstyle $ -             alignFillPath (barPath ofs x y0 y1)+             BarsRight    -> -bsize+             BarsCentered -> -(bsize/2)+       forM_ (zip v2s styles) $ \((v0,v1), (fstyle,_)) ->+           unless (v0 >= v1) $+           withFillStyle fstyle $+             alignFillPath (barPath ofs k v0 v1)              >>= fillPath-       forM_ (zip y2s styles) $ \((y0,y1), (_,mlstyle)) -> -           whenJust mlstyle $ \lstyle -> -              withLineStyle lstyle $ -                alignStrokePath (barPath ofs x y0 y1)+       forM_ (zip v2s styles) $ \((v0,v1), (_,mlstyle)) ->+           unless (v0 >= v1) $+           whenJust mlstyle $ \lstyle ->+              withLineStyle lstyle $+                alignStrokePath (barPath ofs k v0 v1)                 >>= strokePath+       withFontStyle (_bars_settings_label_style p) $+           forM_ (zip v2s lbls) $ \((v0, v1), txt) ->+             unless (null txt) $ do+               let ha = _bars_settings_label_bar_hanchor p+               let va = _bars_settings_label_bar_vanchor p+               let pt = rectCorner ha va (r ofs bsize k v0 v1)+               drawTextR+                  (_bars_settings_label_text_hanchor p)+                  (_bars_settings_label_text_vanchor p)+                  (_bars_settings_label_angle p)+                  (pvadd pt $ _bars_settings_label_offset p)+                  txt -    barPath xos x y0 y1 = do-      let (Point x' y') = pmap' (x,y1)-      let (Point _ y0') = pmap' (x,y0)-      rectPath (Rect (Point (x'+xos) y0') (Point (x'+xos+width) y'))+    styles = _bars_settings_item_styles p -    yref0 = _plot_bars_reference p-    vals  = _plot_bars_values p-    width = case _plot_bars_spacing p of-        BarsFixGap gap minw -> let w = max (minXInterval - gap) minw in-            case _plot_bars_style p of-                BarsClustered -> w / fromIntegral nys+    barPath os k v0 v1 = rectPath $ r os bsize k v0 v1++    bsize = case _bars_settings_spacing p of+        BarsFixGap gap minw -> let w = max (minKInterval - gap) minw in+            case _bars_settings_style p of+                BarsClustered -> w / fromIntegral nvs                 BarsStacked -> w         BarsFixWidth width' -> width'-    styles = _plot_bars_item_styles p -    minXInterval = let diffs = zipWith (-) (tail mxs) mxs+    minKInterval = let diffs = zipWith (-) (tail mks) mks                    in if null diffs-                        then _plot_bars_singleton_width p+                        then _bars_settings_singleton_width p                         else minimum diffs       where-        xs  = fst (allBarPoints p)-        mxs = nub $ sort $ map mapX xs+        mks = nub $ sort $ map (mapk . fst) vals -    nys    = maximum [ length ys | (_,ys) <- vals ]+    nvs = maximum $ map (length . snd) vals -    pmap'  = mapXY pmap-    mapX x = p_x (pmap' (x,barsReference))+rectCorner :: BarHorizAnchor -> BarVertAnchor -> Rect -> Point+rectCorner h v (Rect (Point x0 y0) (Point x1 y1)) = Point x' y' where+    x' = case h of+              BHA_Left   -> x0+              BHA_Right  -> x1+              BHA_Centre -> (x0 + x1) / 2+    y' = case v of+              BVA_Bottom -> y0+              BVA_Top    -> y1+              BVA_Centre -> (y0 + y1) / 2 -whenJust :: (Monad m) => Maybe a -> (a -> m ()) -> m ()-whenJust (Just a) f = f a-whenJust _        _ = return ()+-- Helper function for printing bar values as labels+addLabels :: Show y => [(x, [y])] -> [(x, [(y, String)])]+addLabels = map . second $ map (\y -> (y, show y)) -allBarPoints :: (BarsPlotValue y) => PlotBars x y -> ([x],[y])-allBarPoints p = case _plot_bars_style p of-    BarsClustered -> ( [x| (x,_) <- pts], y0:concat [ys| (_,ys) <- pts] )-    BarsStacked   -> ( [x| (x,_) <- pts], y0:concat [stack ys | (_,ys) <- pts] )-  where-    pts = _plot_bars_values p-    y0  = _plot_bars_reference p+refVal :: (BarsPlotValue y) => BarsSettings -> [(x, [(y, String)])] -> y+refVal p vals = barsReference $ case _bars_settings_style p of+    BarsClustered -> concatMap (map fst . snd) vals+    BarsStacked   -> concatMap (take 1 . dropWhile barsIsNull . stack . map fst . snd) vals +allBarPoints :: (BarsPlotValue y) => BarsSettings -> [(x, [(y, String)])] -> ([x],[y])+allBarPoints p vals = case _bars_settings_style p of+    BarsClustered ->+      let ys = concatMap (map fst) yls in+      ( xs, barsReference ys:ys )+    BarsStacked   ->+      let ys = map (stack . map fst) yls in+      ( xs, barsReference (concatMap (take 1 . dropWhile barsIsNull) ys):concat ys)+  where (xs, yls) = unzip vals+ stack :: (BarsPlotValue y) => [y] -> [y] stack = scanl1 barsAdd  renderPlotLegendBars :: (FillStyle,Maybe LineStyle) -> Rect -> BackendProgram ()-renderPlotLegendBars (fstyle,_) r = -  withFillStyle fstyle $ +renderPlotLegendBars (fstyle,_) r =+  withFillStyle fstyle $     fillPath (rectPath r) +$( makeLenses ''BarsSettings ) $( makeLenses ''PlotBars )++-- Lens provided for backward compat.++-- Note that this one does not satisfy the lens laws, as it discards/overwrites the labels.+plot_bars_values :: Lens' (PlotBars x y) [(x, [y])]+plot_bars_values = lens getter setter+  where+    getter = mapYs fst . _plot_bars_values_with_labels+    setter pb vals' = pb { _plot_bars_values_with_labels = mapYs (, "") vals' }+    mapYs :: (a -> b) -> [(c, [a])] -> [(c, [b])]+    mapYs f = map (over _2 $ map f)++plot_bars_style :: Lens' (PlotBars x y) PlotBarsStyle+plot_bars_style = plot_bars_settings . bars_settings_style++plot_bars_item_styles :: Lens' (PlotBars x y) [(FillStyle, Maybe LineStyle)]+plot_bars_item_styles = plot_bars_settings . bars_settings_item_styles++plot_bars_spacing :: Lens' (PlotBars x y) PlotBarsSpacing+plot_bars_spacing = plot_bars_settings . bars_settings_spacing++plot_bars_alignment :: Lens' (PlotBars x y) PlotBarsAlignment+plot_bars_alignment =  plot_bars_settings . bars_settings_alignment++plot_bars_singleton_width :: Lens' (PlotBars x y) Double+plot_bars_singleton_width = plot_bars_settings . bars_settings_singleton_width++plot_bars_label_bar_hanchor :: Lens' (PlotBars x y) BarHorizAnchor+plot_bars_label_bar_hanchor = plot_bars_settings . bars_settings_label_bar_hanchor++plot_bars_label_bar_vanchor :: Lens' (PlotBars x y) BarVertAnchor+plot_bars_label_bar_vanchor = plot_bars_settings . bars_settings_label_bar_vanchor++plot_bars_label_text_hanchor :: Lens' (PlotBars x y) HTextAnchor+plot_bars_label_text_hanchor = plot_bars_settings . bars_settings_label_text_hanchor++plot_bars_label_text_vanchor :: Lens' (PlotBars x y) VTextAnchor+plot_bars_label_text_vanchor = plot_bars_settings . bars_settings_label_text_vanchor++plot_bars_label_angle :: Lens' (PlotBars x y) Double+plot_bars_label_angle = plot_bars_settings . bars_settings_label_angle++plot_bars_label_style :: Lens' (PlotBars x y) FontStyle+plot_bars_label_style = plot_bars_settings . bars_settings_label_style++plot_bars_label_offset :: Lens' (PlotBars x y) Vector+plot_bars_label_offset = plot_bars_settings . bars_settings_label_offset
Graphics/Rendering/Chart/Plot/Candle.hs view
@@ -24,7 +24,6 @@ ) where  import Control.Lens hiding (op)-import Data.Monoid  import Graphics.Rendering.Chart.Geometry hiding (close) import Graphics.Rendering.Chart.Drawing@@ -75,7 +74,7 @@         pts = _plot_candle_values p  renderPlotCandle :: PlotCandle x y -> PointMapFn x y -> BackendProgram ()-renderPlotCandle p pmap = +renderPlotCandle p pmap =     mapM_ (drawCandle p . candlemap) (_plot_candle_values p)   where     candlemap (Candle x lo op mid cl hi) =@@ -96,7 +95,7 @@         -- the pixel coordinate system is inverted wrt the value coords.         when f $ withFillStyle (if open >= close                                    then _plot_candle_rise_fill_style ps-                                   else _plot_candle_fall_fill_style ps) $ +                                   else _plot_candle_fall_fill_style ps) $                     fillPath $ moveTo' (x-wd) open                             <> lineTo' (x-wd) close                             <> lineTo' (x+wd) close@@ -119,7 +118,7 @@                                     <> lineTo' (x+tl) lo                                     <> moveTo' (x-tl) hi                                     <> lineTo' (x+tl) hi-          +           when (ct > 0) $ strokePath $ moveTo' (x-ct) mid                                     <> lineTo' (x+ct) mid @@ -137,7 +136,7 @@     close = (mid + hi) / 2  instance Default (PlotCandle x y) where-  def = PlotCandle +  def = PlotCandle     { _plot_candle_title       = ""     , _plot_candle_line_style  = solidLine 1 $ opaque blue     , _plot_candle_fill        = False
Graphics/Rendering/Chart/Plot/ErrBars.hs view
@@ -25,7 +25,6 @@ ) where  import Control.Lens-import Data.Monoid  import Graphics.Rendering.Chart.Geometry import Graphics.Rendering.Chart.Drawing@@ -76,7 +75,7 @@         pts = _plot_errbars_values p  renderPlotErrBars :: PlotErrBars x y -> PointMapFn x y -> BackendProgram ()-renderPlotErrBars p pmap = +renderPlotErrBars p pmap =     mapM_ (drawErrBar.epmap) (_plot_errbars_values p)   where     epmap (ErrPoint (ErrValue xl x xh) (ErrValue yl y yh)) =@@ -91,7 +90,7 @@ drawErrBar0 ps (ErrPoint (ErrValue xl x xh) (ErrValue yl y yh)) = do         let tl = _plot_errbars_tick_length ps         let oh = _plot_errbars_overhang ps-        withLineStyle (_plot_errbars_line_style ps) $ +        withLineStyle (_plot_errbars_line_style ps) $           strokePath $ moveTo' (xl-oh) y                     <> lineTo' (xh+oh) y                     <> moveTo' x (yl-oh)@@ -117,7 +116,7 @@     y          = (p_y p1 + p_y p2)/2  instance Default (PlotErrBars x y) where-  def = PlotErrBars +  def = PlotErrBars     { _plot_errbars_title       = ""     , _plot_errbars_line_style  = solidLine 1 $ opaque blue     , _plot_errbars_tick_length = 3
Graphics/Rendering/Chart/Plot/Histogram.hs view
@@ -7,6 +7,7 @@   , defaultPlotHist   , defaultFloatPlotHist   , defaultNormedPlotHist+  , histToBins     -- * Accessors   , plot_hist_title   , plot_hist_bins@@ -20,7 +21,6 @@   ) where  import Control.Monad (when)-import Data.Monoid import Data.Maybe (fromMaybe) import qualified Data.Foldable as F import qualified Data.Vector as V@@ -161,6 +161,7 @@         let y = (p_y p1 + p_y p2) / 2         in strokePath $ moveTo' (p_x p1) y <> lineTo' (p_x p2) y +-- | Obtain the bin dimensions of a given @PlotHist@. histToBins :: (RealFrac x, Num y, Ord y) => PlotHist x y -> [((x,x), y)] histToBins hist =     filter_zeros $ zip bounds $ counts
Graphics/Rendering/Chart/Plot/Pie.hs view
@@ -1,229 +1,228 @@------------------------------------------------------------------------------
--- |
--- Module      :  Graphics.Rendering.Chart.Plot.Pie
--- Copyright   :  (c) Tim Docker 2008, 2014
--- License     :  BSD-style (see chart/COPYRIGHT)
---
--- A  basic pie chart.
---
--- Pie charts are handled different to other plots, in that they
--- have their own layout, and can't be composed with other plots. A
--- pie chart is rendered with code in the following form:
---
--- @
--- values :: [PieItem]
--- values = [...]
--- layout :: PieLayout
--- layout = pie_plot ^: pie_data ^= values
---        $ def
--- renderable = toRenderable layout
--- @
-{-# LANGUAGE TemplateHaskell #-}
-
-module Graphics.Rendering.Chart.Plot.Pie(
-    PieLayout(..),
-    PieChart(..),
-    PieItem(..),
-    
-    pieToRenderable,
-    pieChartToRenderable,
-
-    pie_title,
-    pie_title_style,
-    pie_plot,
-    pie_background,
-    pie_margin,
-    pie_data,
-    pie_colors,
-    pie_label_style,
-    pie_label_line_style,
-    pie_start_angle,
-    pitem_label,
-    pitem_offset,
-    pitem_value,
-
-) where
--- original code thanks to Neal Alexander
-
--- see ../Drawing.hs for why we do not use hiding (moveTo) for
--- lens < 4
-import Control.Lens
-import Data.Colour
-import Data.Colour.Names (white)
-import Data.Monoid
-import Data.Default.Class
-import Control.Monad
-
-import Graphics.Rendering.Chart.Geometry hiding (moveTo)
-import qualified Graphics.Rendering.Chart.Geometry as G
-import Graphics.Rendering.Chart.Drawing
-import Graphics.Rendering.Chart.Renderable
-import Graphics.Rendering.Chart.Grid
-
-data PieLayout = PieLayout {
-   _pie_title       :: String,
-   _pie_title_style :: FontStyle,
-   _pie_plot        :: PieChart,
-   _pie_background  :: FillStyle,
-   _pie_margin      :: Double
-}
-
-data PieChart = PieChart {
-   _pie_data             :: [PieItem],
-   _pie_colors           :: [AlphaColour Double],
-   _pie_label_style      :: FontStyle,
-   _pie_label_line_style :: LineStyle, 
-   _pie_start_angle      :: Double
-
-}
-
-data PieItem = PieItem {
-   _pitem_label  :: String,
-   _pitem_offset :: Double,
-   _pitem_value  :: Double
-}
-
-instance Default PieChart where
-  def = PieChart 
-    { _pie_data             = []
-    , _pie_colors           = defaultColorSeq
-    , _pie_label_style      = def
-    , _pie_label_line_style = solidLine 1 $ opaque black
-    , _pie_start_angle      = 0
-    }
-
-instance Default PieItem where
-  def = PieItem "" 0 0
-
-instance Default PieLayout where
-  def = PieLayout 
-    { _pie_background  = solidFillStyle $ opaque white
-    , _pie_title       = ""
-    , _pie_title_style = def { _font_size   = 15
-                             , _font_weight = FontWeightBold }
-    , _pie_plot        = def
-    , _pie_margin      = 10
-    }
-
-instance ToRenderable PieLayout where
-  toRenderable = setPickFn nullPickFn . pieToRenderable
-
-pieChartToRenderable :: PieChart -> Renderable (PickFn a)
-pieChartToRenderable p = Renderable { minsize = minsizePie p
-                                    , render  = renderPie p
-                                    }
-
-instance ToRenderable PieChart where
-  toRenderable = setPickFn nullPickFn . pieChartToRenderable
-
-pieToRenderable :: PieLayout -> Renderable (PickFn a)
-pieToRenderable p = fillBackground (_pie_background p) (
-       gridToRenderable $ aboveN
-         [ tval $ addMargins (lm/2,0,0,0) (setPickFn nullPickFn title)
-         , weights (1,1) $ tval $ addMargins (lm,lm,lm,lm)
-                                             (pieChartToRenderable $ _pie_plot p)
-         ] )
-      where
-        title = label (_pie_title_style p) HTA_Centre VTA_Top (_pie_title p)
-        lm    = _pie_margin p
-
-extraSpace :: PieChart -> BackendProgram (Double, Double)
-extraSpace p = do
-    textSizes <- mapM (textDimension . _pitem_label) (_pie_data p)
-    let maxw  = foldr (max.fst) 0 textSizes
-    let maxh  = foldr (max.snd) 0 textSizes
-    let maxo  = foldr (max._pitem_offset) 0 (_pie_data p)
-    let extra = label_rgap + label_rlength + maxo
-    return (extra + maxw, extra + maxh )
-
-minsizePie :: PieChart -> BackendProgram (Double, Double)
-minsizePie p = do
-    (extraw,extrah) <- extraSpace p
-    return (extraw * 2, extrah * 2)
-
-renderPie :: PieChart -> (Double, Double) -> BackendProgram (PickFn a)
-renderPie p (w,h) = do
-    (extraw,extrah) <- extraSpace p
-    -- let (w,h)  = (p_x p2 - p_x p1, p_y p2 - p_y p1)
-    -- let center = Point (p_x p1 + w/2)  (p_y p1 + h/2)
-    --
-    let center = Point (w/2) (h/2)
-    let radius = min (w - 2*extraw) (h - 2*extrah) / 2
-
-    foldM_ (paint center radius) (_pie_start_angle p)
-           (zip (_pie_colors p) content)
-    return nullPickFn
- 
-    where
-        -- p1 = Point 0 0 
-        -- p2 = Point w h 
-        content = let total = sum (map _pitem_value (_pie_data p))
-                  in [ pitem{_pitem_value=_pitem_value pitem/total}
-                     | pitem <- _pie_data p ]
-
-        paint :: Point -> Double -> Double -> (AlphaColour Double, PieItem)
-              -> BackendProgram Double
-        paint center radius a1 (color,pitem) = do
-            let ax     = 360.0 * _pitem_value pitem
-            let a2     = a1 + (ax / 2)
-            let a3     = a1 + ax
-            let offset = _pitem_offset pitem
-
-            pieSlice (ray a2 offset) a1 a3 color
-            pieLabel (_pitem_label pitem) a2 offset
-
-            return a3
-
-            where
-                pieLabel :: String -> Double -> Double -> BackendProgram ()
-                pieLabel name angle offset = 
-                    withFontStyle (_pie_label_style p) $ 
-                      withLineStyle (_pie_label_line_style p) $ do
-                        let p1 = ray angle (radius+label_rgap+label_rlength+offset)
-                        p1a <- alignStrokePoint p1
-                        (tw,_) <- textDimension name
-                        let (offset',anchor) = if angle < 90 || angle > 270 
-                                              then ((0+),HTA_Left)
-                                              else ((0-),HTA_Right)
-                        p0 <- alignStrokePoint $ ray angle (radius + label_rgap+offset)
-                        strokePath $ G.moveTo p0
-                                  <> lineTo p1a
-                                  <> lineTo' (p_x p1a + offset' (tw + label_rgap)) (p_y p1a)
-
-                        let p2 = p1 `pvadd` Vector (offset' label_rgap) 0
-                        drawTextA anchor VTA_Bottom p2 name
-
-                pieSlice :: Point -> Double -> Double -> AlphaColour Double -> BackendProgram ()
-                pieSlice (Point x y) arc1 arc2 pColor = do
-                    let path = arc' x y radius (radian arc1) (radian arc2)
-                            <> lineTo' x y
-                            <> lineTo' x y
-                            <> close
-
-                    withFillStyle (FillStyleSolid pColor) $ 
-                      fillPath path
-                    withLineStyle (def { _line_color = withOpacity white 0.1 }) $ 
-                      strokePath path
-
-                ray :: Double -> Double -> Point
-                ray angle r = Point x' y'
-                  where
-                    x'   = x + (cos' * x'')
-                    y'   = y + (sin' * x'')
-                    cos' = (cos . radian) angle
-                    sin' = (sin . radian) angle
-                    -- TODO: is x'' defined in this way to try and avoid
-                    --       numerical rounding?
-                    x''  = (x + r) - x
-                    x    = p_x center
-                    y    = p_y center
-
-                radian = (*(pi / 180.0))
-
-label_rgap, label_rlength :: Double
-label_rgap = 5
-label_rlength = 15
-
-$( makeLenses ''PieLayout )
-$( makeLenses ''PieChart )
-$( makeLenses ''PieItem )
+-----------------------------------------------------------------------------+-- |+-- Module      :  Graphics.Rendering.Chart.Plot.Pie+-- Copyright   :  (c) Tim Docker 2008, 2014+-- License     :  BSD-style (see chart/COPYRIGHT)+--+-- A  basic pie chart.+--+-- Pie charts are handled different to other plots, in that they+-- have their own layout, and can't be composed with other plots. A+-- pie chart is rendered with code in the following form:+--+-- @+-- values :: [PieItem]+-- values = [...]+-- layout :: PieLayout+-- layout = pie_plot ^: pie_data ^= values+--        $ def+-- renderable = toRenderable layout+-- @+{-# LANGUAGE TemplateHaskell #-}++module Graphics.Rendering.Chart.Plot.Pie(+    PieLayout(..),+    PieChart(..),+    PieItem(..),++    pieToRenderable,+    pieChartToRenderable,++    pie_title,+    pie_title_style,+    pie_plot,+    pie_background,+    pie_margin,+    pie_data,+    pie_colors,+    pie_label_style,+    pie_label_line_style,+    pie_start_angle,+    pitem_label,+    pitem_offset,+    pitem_value,++) where+-- original code thanks to Neal Alexander++-- see ../Drawing.hs for why we do not use hiding (moveTo) for+-- lens < 4+import Control.Lens+import Data.Colour+import Data.Colour.Names (white)+import Data.Default.Class+import Control.Monad++import Graphics.Rendering.Chart.Geometry hiding (moveTo)+import qualified Graphics.Rendering.Chart.Geometry as G+import Graphics.Rendering.Chart.Drawing+import Graphics.Rendering.Chart.Renderable+import Graphics.Rendering.Chart.Grid++data PieLayout = PieLayout {+   _pie_title       :: String,+   _pie_title_style :: FontStyle,+   _pie_plot        :: PieChart,+   _pie_background  :: FillStyle,+   _pie_margin      :: Double+}++data PieChart = PieChart {+   _pie_data             :: [PieItem],+   _pie_colors           :: [AlphaColour Double],+   _pie_label_style      :: FontStyle,+   _pie_label_line_style :: LineStyle,+   _pie_start_angle      :: Double++}++data PieItem = PieItem {+   _pitem_label  :: String,+   _pitem_offset :: Double,+   _pitem_value  :: Double+}++instance Default PieChart where+  def = PieChart+    { _pie_data             = []+    , _pie_colors           = defaultColorSeq+    , _pie_label_style      = def+    , _pie_label_line_style = solidLine 1 $ opaque black+    , _pie_start_angle      = 0+    }++instance Default PieItem where+  def = PieItem "" 0 0++instance Default PieLayout where+  def = PieLayout+    { _pie_background  = solidFillStyle $ opaque white+    , _pie_title       = ""+    , _pie_title_style = def { _font_size   = 15+                             , _font_weight = FontWeightBold }+    , _pie_plot        = def+    , _pie_margin      = 10+    }++instance ToRenderable PieLayout where+  toRenderable = setPickFn nullPickFn . pieToRenderable++pieChartToRenderable :: PieChart -> Renderable (PickFn a)+pieChartToRenderable p = Renderable { minsize = minsizePie p+                                    , render  = renderPie p+                                    }++instance ToRenderable PieChart where+  toRenderable = setPickFn nullPickFn . pieChartToRenderable++pieToRenderable :: PieLayout -> Renderable (PickFn a)+pieToRenderable p = fillBackground (_pie_background p) (+       gridToRenderable $ aboveN+         [ tval $ addMargins (lm/2,0,0,0) (setPickFn nullPickFn title)+         , weights (1,1) $ tval $ addMargins (lm,lm,lm,lm)+                                             (pieChartToRenderable $ _pie_plot p)+         ] )+      where+        title = label (_pie_title_style p) HTA_Centre VTA_Top (_pie_title p)+        lm    = _pie_margin p++extraSpace :: PieChart -> BackendProgram (Double, Double)+extraSpace p = do+    textSizes <- mapM (textDimension . _pitem_label) (_pie_data p)+    let maxw  = foldr (max.fst) 0 textSizes+    let maxh  = foldr (max.snd) 0 textSizes+    let maxo  = foldr (max._pitem_offset) 0 (_pie_data p)+    let extra = label_rgap + label_rlength + maxo+    return (extra + maxw, extra + maxh )++minsizePie :: PieChart -> BackendProgram (Double, Double)+minsizePie p = do+    (extraw,extrah) <- extraSpace p+    return (extraw * 2, extrah * 2)++renderPie :: PieChart -> (Double, Double) -> BackendProgram (PickFn a)+renderPie p (w,h) = do+    (extraw,extrah) <- extraSpace p+    -- let (w,h)  = (p_x p2 - p_x p1, p_y p2 - p_y p1)+    -- let center = Point (p_x p1 + w/2)  (p_y p1 + h/2)+    --+    let center = Point (w/2) (h/2)+    let radius = min (w - 2*extraw) (h - 2*extrah) / 2++    foldM_ (paint center radius) (_pie_start_angle p)+           (zip (_pie_colors p) content)+    return nullPickFn++    where+        -- p1 = Point 0 0+        -- p2 = Point w h+        content = let total = sum (map _pitem_value (_pie_data p))+                  in [ pitem{_pitem_value=_pitem_value pitem/total}+                     | pitem <- _pie_data p ]++        paint :: Point -> Double -> Double -> (AlphaColour Double, PieItem)+              -> BackendProgram Double+        paint center radius a1 (color,pitem) = do+            let ax     = 360.0 * _pitem_value pitem+            let a2     = a1 + (ax / 2)+            let a3     = a1 + ax+            let offset = _pitem_offset pitem++            pieSlice (ray a2 offset) a1 a3 color+            pieLabel (_pitem_label pitem) a2 offset++            return a3++            where+                pieLabel :: String -> Double -> Double -> BackendProgram ()+                pieLabel name angle offset =+                    withFontStyle (_pie_label_style p) $+                      withLineStyle (_pie_label_line_style p) $ do+                        let p1 = ray angle (radius+label_rgap+label_rlength+offset)+                        p1a <- alignStrokePoint p1+                        (tw,_) <- textDimension name+                        let (offset',anchor) = if angle < 90 || angle > 270+                                              then ((0+),HTA_Left)+                                              else ((0-),HTA_Right)+                        p0 <- alignStrokePoint $ ray angle (radius + label_rgap+offset)+                        strokePath $ G.moveTo p0+                                  <> lineTo p1a+                                  <> lineTo' (p_x p1a + offset' (tw + label_rgap)) (p_y p1a)++                        let p2 = p1 `pvadd` Vector (offset' label_rgap) 0+                        drawTextA anchor VTA_Bottom p2 name++                pieSlice :: Point -> Double -> Double -> AlphaColour Double -> BackendProgram ()+                pieSlice (Point x y) arc1 arc2 pColor = do+                    let path = arc' x y radius (radian arc1) (radian arc2)+                            <> lineTo' x y+                            <> lineTo' x y+                            <> close++                    withFillStyle (FillStyleSolid pColor) $+                      fillPath path+                    withLineStyle (def { _line_color = withOpacity white 0.1 }) $+                      strokePath path++                ray :: Double -> Double -> Point+                ray angle r = Point x' y'+                  where+                    x'   = x + (cos' * x'')+                    y'   = y + (sin' * x'')+                    cos' = (cos . radian) angle+                    sin' = (sin . radian) angle+                    -- TODO: is x'' defined in this way to try and avoid+                    --       numerical rounding?+                    x''  = (x + r) - x+                    x    = p_x center+                    y    = p_y center++                radian = (*(pi / 180.0))++label_rgap, label_rlength :: Double+label_rgap = 5+label_rlength = 15++$( makeLenses ''PieLayout )+$( makeLenses ''PieChart )+$( makeLenses ''PieItem )
Graphics/Rendering/Chart/Renderable.hs view
@@ -17,7 +17,7 @@     PickFn,     Rectangle(..),     RectCornerStyle(..),-    +     rectangleToRenderable,     drawRectangle, @@ -42,7 +42,6 @@  import Control.Monad import Control.Lens-import Data.Monoid import Data.Default.Class  import Graphics.Rendering.Chart.Geometry@@ -84,7 +83,7 @@ emptyRenderable = spacer (0,0)  -- | Create a blank renderable with a specified minimum size.-spacer :: RectSize -> Renderable a +spacer :: RectSize -> Renderable a spacer sz  = Renderable {    minsize = return sz,    render  = \_ -> return nullPickFn@@ -119,7 +118,7 @@         (w,h) <- minsize rd         return (w+l+r,h+t+b) -    rf (w,h) = +    rf (w,h) =         withTranslation (Point l t) $ do           pickf <- render rd (w-l-r,h-t-b)           return (mkpickf pickf (t,b,l,r) (w,h))@@ -163,27 +162,27 @@        ts <- textSize s        let sz = (textSizeWidth ts, textSizeHeight ts)        return (xwid sz, ywid sz)-       +     rf (w0,h0) = withFontStyle fs $ do       ts <- textSize s       let sz@(w,h) = (textSizeWidth ts, textSizeHeight ts)           descent = textSizeDescent ts-          +           xadj HTA_Left   = xwid sz/2           xadj HTA_Centre = w0/2           xadj HTA_Right  = w0 - xwid sz/2-    +           yadj VTA_Top      = ywid sz/2           yadj VTA_Centre   = h0/2           yadj VTA_Bottom   = h0 - ywid sz/2           yadj VTA_BaseLine = h0 - ywid sz/2 + descent*acr -      withTranslation (Point 0 (-descent)) $ -        withTranslation (Point (xadj hta) (yadj vta)) $ +      withTranslation (Point 0 (-descent)) $+        withTranslation (Point (xadj hta) (yadj vta)) $           withRotation rot' $ do             drawText (Point (-w/2) (h/2)) s             return (\_-> Just s)  -- PickFn String-            +     rot'      = rot / 180 * pi     (cr,sr)   = (cos rot', sin rot')     (acr,asr) = (abs cr, abs sr)@@ -232,22 +231,22 @@   return nullPickFn     where       size = _rect_minsize rectangle- -      fill p sz fs = -          withFillStyle fs $ ++      fill p sz fs =+          withFillStyle fs $             fillPath $ strokeRectangleP p sz (_rect_cornerStyle rectangle)- -      stroke p sz ls = -          withLineStyle ls $ ++      stroke p sz ls =+          withLineStyle ls $             strokePath $ strokeRectangleP p sz (_rect_cornerStyle rectangle)- +       strokeRectangleP (Point x1 y1) (x2,y2) RCornerSquare =           let (x3,y3) = (x1+x2,y1+y2) in moveTo' x1 y1                                       <> lineTo' x1 y3                                       <> lineTo' x3 y3                                       <> lineTo' x3 y1                                       <> lineTo' x1 y1-                                  +       strokeRectangleP (Point x1 y1) (x2,y2) (RCornerBevel s) =           let (x3,y3) = (x1+x2,y1+y2) in moveTo' x1 (y1+s)                                       <> lineTo' x1 (y3-s)@@ -258,7 +257,7 @@                                       <> lineTo' (x3-s) y1                                       <> lineTo' (x1+s) y1                                       <> lineTo' x1 (y1+s)- +       strokeRectangleP (Point x1 y1) (x2,y2) (RCornerRounded s) =           let (x3,y3) = (x1+x2,y1+y2) in             arcNeg (Point (x1+s) (y3-s)) s (pi2*2) pi2@@ -266,7 +265,7 @@             <> arcNeg (Point (x3-s) (y1+s)) s 0 (pi2*3)             <> arcNeg (Point (x1+s) (y1+s)) s (pi2*3) (pi2*2)             <> lineTo' x1 (y3-s)-      +       pi2 = pi / 2  $( makeLenses ''Rectangle )
Graphics/Rendering/Chart/Utils.hs view
@@ -1,16 +1,24 @@ -- | Non chart specific utility functions. module Graphics.Rendering.Chart.Utils(     isValidNumber,+    log10,     maybeM,+    whenJust,   ) where --- | Checks if the given value is and actual numeric value and not +-- | Checks if the given value is and actual numeric value and not --   a concept like NaN or infinity. isValidNumber :: (RealFloat a) => a -> Bool isValidNumber v = not (isNaN v) && not (isInfinite v) +-- | Shorthand for the decimal logarithm+log10 :: (Floating a) => a -> a+log10 = logBase 10+ -- | Version of 'Prelude.maybe' that returns a monadic value. maybeM :: (Monad m) => b -> (a -> m b) -> Maybe a -> m b maybeM v = maybe (return v) -+-- | Specialization to ()+whenJust :: (Monad m) => Maybe a -> (a -> m ()) -> m ()+whenJust m f = maybeM () f m